summaryrefslogtreecommitdiff
authorzecke <zecke>2004-11-18 21:49:23 (UTC)
committer zecke <zecke>2004-11-18 21:49:23 (UTC)
commit1e7f8f22fc10e3ed85b6563332ddc348c95792d0 (patch) (unidiff)
tree59498ba1d4a7dbff05228c09bebcf0c849e916be
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 (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,37 +1,40 @@
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
34!contains( ENABLE_SQL_PIM_BACKEND, y ) { 37!contains( ENABLE_SQL_PIM_BACKEND, y ) {
35 message ( No SQL Backend in libopiepim2 ) 38 message ( No SQL Backend in libopiepim2 )
36} 39}
37 40
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
@@ -41,92 +41,94 @@
41#include <opie2/otodoaccessvcal.h> 41#include <opie2/otodoaccessvcal.h>
42#include <opie2/ocontactaccessbackend_xml.h> 42#include <opie2/ocontactaccessbackend_xml.h>
43#include <opie2/ocontactaccessbackend_vcard.h> 43#include <opie2/ocontactaccessbackend_vcard.h>
44#include <opie2/odatebookaccessbackend_xml.h> 44#include <opie2/odatebookaccessbackend_xml.h>
45#include <opie2/odebug.h> 45#include <opie2/odebug.h>
46 46
47#ifdef __USE_SQL 47#ifdef __USE_SQL
48#include <opie2/otodoaccesssql.h> 48#include <opie2/otodoaccesssql.h>
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 );
125 break; 127 break;
126 } 128 }
127 case OPimGlobal::CONTACTLIST: 129 case OPimGlobal::CONTACTLIST:
128 switch ( use_database ){ 130 switch ( use_database ){
129 default: // Use SQL if something weird is given. 131 default: // Use SQL if something weird is given.
130 // Fall through !! 132 // Fall through !!
131 case OPimGlobal::SQL: 133 case OPimGlobal::SQL:
132#ifdef __USE_SQL 134#ifdef __USE_SQL
@@ -145,86 +147,86 @@ class OBackendPrivate;
145 } 147 }
146 case OPimGlobal::DATEBOOK: 148 case OPimGlobal::DATEBOOK:
147 switch ( use_database ){ 149 switch ( use_database ){
148 default: // Use SQL if something weird is given. 150 default: // Use SQL if something weird is given.
149 // Fall through !! 151 // Fall through !!
150 case OPimGlobal::SQL: 152 case OPimGlobal::SQL:
151#ifdef __USE_SQL 153#ifdef __USE_SQL
152 return (T*) new ODateBookAccessBackend_SQL( appName, filename ); 154 return (T*) new ODateBookAccessBackend_SQL( appName, filename );
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
@@ -36,79 +36,73 @@
36 * 36 *
37 */ 37 */
38 38
39#ifndef _OCONTACTACCESSBACKEND_H_ 39#ifndef _OCONTACTACCESSBACKEND_H_
40#define _OCONTACTACCESSBACKEND_H_ 40#define _OCONTACTACCESSBACKEND_H_
41 41
42#include <opie2/opimcontact.h> 42#include <opie2/opimcontact.h>
43#include <opie2/opimaccessbackend.h> 43#include <opie2/opimaccessbackend.h>
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
@@ -146,87 +146,64 @@ bool OPimContactAccessBackend_VCard::remove ( int uid )
146bool OPimContactAccessBackend_VCard::replace ( const OPimContact &contact ) 146bool OPimContactAccessBackend_VCard::replace ( const OPimContact &contact )
147{ 147{
148 m_map.replace( contact.uid(), contact ); 148 m_map.replace( contact.uid(), contact );
149 m_dirty = true; 149 m_dirty = true;
150 return true; 150 return true;
151} 151}
152 152
153OPimContact OPimContactAccessBackend_VCard::find ( int uid ) const 153OPimContact 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 );
225 QCString name = vObjectTypeInfo( o ); 202 QCString name = vObjectTypeInfo( o );
226 QString value = QString::fromUtf8( vObjectStringZValue( o ) ); 203 QString value = QString::fromUtf8( vObjectStringZValue( o ) );
227 odebug << "(2)Read: %s" << value.latin1() << oendl; 204 odebug << "(2)Read: %s" << value.latin1() << oendl;
228 if ( name == VCNamePrefixesProp ) 205 if ( name == VCNamePrefixesProp )
229 c.setTitle( value ); 206 c.setTitle( value );
230 else if ( name == VCNameSuffixesProp ) 207 else if ( name == VCNameSuffixesProp )
231 c.setSuffix( value ); 208 c.setSuffix( value );
232 else if ( name == VCFamilyNameProp ) 209 else if ( name == VCFamilyNameProp )
@@ -299,49 +276,48 @@ OPimContact OPimContactAccessBackend_VCard::parseVObject( VObject *obj )
299 QCString name = vObjectTypeInfo( o ); 276 QCString name = vObjectTypeInfo( o );
300 if ( name == VCHomeProp ) 277 if ( name == VCHomeProp )
301 type |= HOME; 278 type |= HOME;
302 else if ( name == VCWorkProp ) 279 else if ( name == VCWorkProp )
303 type |= WORK; 280 type |= WORK;
304 else if ( name == VCVoiceProp ) 281 else if ( name == VCVoiceProp )
305 type |= VOICE; 282 type |= VOICE;
306 else if ( name == VCCellularProp ) 283 else if ( name == VCCellularProp )
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 }
340 else if ( name == VCEmailAddressProp ) { 316 else if ( name == VCEmailAddressProp ) {
341 QString email = QString::fromUtf8( vObjectStringZValue( o ) ); 317 QString email = QString::fromUtf8( vObjectStringZValue( o ) );
342 bool valid = TRUE; 318 bool valid = TRUE;
343 VObjectIterator nit; 319 VObjectIterator nit;
344 initPropIterator( &nit, o ); 320 initPropIterator( &nit, o );
345 while( moreIteration( &nit ) ) { 321 while( moreIteration( &nit ) ) {
346 VObject *o = nextVObject( &nit ); 322 VObject *o = nextVObject( &nit );
347 QCString name = vObjectTypeInfo( o ); 323 QCString name = vObjectTypeInfo( o );
@@ -504,68 +480,66 @@ VObject* OPimContactAccessBackend_VCard::createVObject( const OPimContact &c )
504 safeAddProp( work_phone, VCWorkProp ); 480 safeAddProp( work_phone, VCWorkProp );
505 safeAddProp( work_phone, VCFaxProp ); 481 safeAddProp( work_phone, VCFaxProp );
506 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() ); 482 work_phone = safeAddPropValue( vcard, VCTelephoneProp, c.businessPager() );
507 safeAddProp( work_phone, VCWorkProp ); 483 safeAddProp( work_phone, VCWorkProp );
508 safeAddProp( work_phone, VCPagerProp ); 484 safeAddProp( work_phone, VCPagerProp );
509 485
510 url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() ); 486 url = safeAddPropValue( vcard, VCURLProp, c.businessWebpage() );
511 safeAddProp( url, VCWorkProp ); 487 safeAddProp( url, VCWorkProp );
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;
564 while ( ( pos = str_rfc2425.find (' ') ) > 0 ) 538 while ( ( pos = str_rfc2425.find (' ') ) > 0 )
565 str_rfc2425.replace( pos, 1, "0" ); 539 str_rfc2425.replace( pos, 1, "0" );
566 540
567 return str_rfc2425; 541 return str_rfc2425;
568} 542}
569 543
570QDate OPimContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr ) 544QDate OPimContactAccessBackend_VCard::convVCardDateToDate( const QString& datestr )
571{ 545{
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
@@ -38,48 +38,45 @@
38 38
39class VObject; 39class VObject;
40 40
41namespace Opie { 41namespace Opie {
42/** 42/**
43 * This is the vCard 2.1 implementation of the Contact Storage 43 * This is the vCard 2.1 implementation of the Contact Storage
44 * @see OPimContactAccessBackend_XML 44 * @see OPimContactAccessBackend_XML
45 * @see OPimAccessBackend 45 * @see OPimAccessBackend
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}
84 81
85#endif 82#endif
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
@@ -87,79 +87,76 @@ bool OPimContactAccessBackend_XML::save()
87 return true; 87 return true;
88 88
89 QString strNewFile = m_fileName + ".new"; 89 QString strNewFile = m_fileName + ".new";
90 QFile f( strNewFile ); 90 QFile f( strNewFile );
91 if ( !f.open( IO_WriteOnly|IO_Raw ) ) 91 if ( !f.open( IO_WriteOnly|IO_Raw ) )
92 return false; 92 return false;
93 93
94 int total_written; 94 int total_written;
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
158 /* Load XML-File and journal if it exists */ 155 /* Load XML-File and journal if it exists */
159 if ( !load ( m_fileName, false ) ) 156 if ( !load ( m_fileName, false ) )
160 return false; 157 return false;
161 /* The returncode of the journalfile is ignored due to the 158 /* The returncode of the journalfile is ignored due to the
162 * fact that it does not exist when this class is instantiated ! 159 * fact that it does not exist when this class is instantiated !
163 * But there may such a file exist, if the application crashed. 160 * But there may such a file exist, if the application crashed.
164 * Therefore we try to load it to get the changes before the # 161 * Therefore we try to load it to get the changes before the #
165 * crash happened... 162 * crash happened...
@@ -192,51 +189,50 @@ QArray<int> OPimContactAccessBackend_XML::allRecords() const
192 189
193 uint counter = 0; 190 uint counter = 0;
194 QListIterator<OPimContact> it( m_contactList ); 191 QListIterator<OPimContact> it( m_contactList );
195 for( ; it.current(); ++it ){ 192 for( ; it.current(); ++it ){
196 uid_list[counter++] = (*it)->uid(); 193 uid_list[counter++] = (*it)->uid();
197 } 194 }
198 195
199 return ( uid_list ); 196 return ( uid_list );
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:
235 queryDate = new QDate( query.birthday() ); 231 queryDate = new QDate( query.birthday() );
236 checkDate = new QDate( (*it)->birthday() ); 232 checkDate = new QDate( (*it)->birthday() );
237 // fall through 233 // fall through
238 case Qtopia::Anniversary: 234 case Qtopia::Anniversary:
239 if ( queryDate == 0l ){ 235 if ( queryDate == 0l ){
240 queryDate = new QDate( query.anniversary() ); 236 queryDate = new QDate( query.anniversary() );
241 checkDate = new QDate( (*it)->anniversary() ); 237 checkDate = new QDate( (*it)->anniversary() );
242 } 238 }
@@ -257,55 +253,52 @@ QArray<int> OPimContactAccessBackend_XML::queryByExample ( const OPimContact &qu
257 } 253 }
258 if ( settings & OPimContactAccess::DateDiff ) { 254 if ( settings & OPimContactAccess::DateDiff ) {
259 QDate current; 255 QDate current;
260 // If we get an additional date, we 256 // If we get an additional date, we
261 // will take this date instead of 257 // will take this date instead of
262 // the current one.. 258 // the current one..
263 if ( !d.date().isValid() ) 259 if ( !d.date().isValid() )
264 current = QDate::currentDate(); 260 current = QDate::currentDate();
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 */
304 if ( !query.field(i).isEmpty() ){ 297 if ( !query.field(i).isEmpty() ){
305 switch ( settings & ~( OPimContactAccess::IgnoreCase 298 switch ( settings & ~( OPimContactAccess::IgnoreCase
306 | OPimContactAccess::DateDiff 299 | OPimContactAccess::DateDiff
307 | OPimContactAccess::DateYear 300 | OPimContactAccess::DateYear
308 | OPimContactAccess::DateMonth 301 | OPimContactAccess::DateMonth
309 | OPimContactAccess::DateDay 302 | OPimContactAccess::DateDay
310 | OPimContactAccess::MatchOne 303 | OPimContactAccess::MatchOne
311 ) ){ 304 ) ){
@@ -409,105 +402,105 @@ bool OPimContactAccessBackend_XML::hasQuerySettings (uint querySettings) const
409 if ( querySettings == OPimContactAccess::IgnoreCase ) 402 if ( querySettings == OPimContactAccess::IgnoreCase )
410 return false; 403 return false;
411 404
412 // WildCards, RegExp and ExactMatch should never used at the same time 405 // WildCards, RegExp and ExactMatch should never used at the same time
413 switch ( querySettings & ~( OPimContactAccess::IgnoreCase 406 switch ( querySettings & ~( OPimContactAccess::IgnoreCase
414 | OPimContactAccess::DateDiff 407 | OPimContactAccess::DateDiff
415 | OPimContactAccess::DateYear 408 | OPimContactAccess::DateYear
416 | OPimContactAccess::DateMonth 409 | OPimContactAccess::DateMonth
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
506 return true; 499 return true;
507 } else 500 } else
508 return false; 501 return false;
509} 502}
510 503
511bool OPimContactAccessBackend_XML::reload(){ 504bool OPimContactAccessBackend_XML::reload(){
512 /* Reload is the same as load in this implementation */ 505 /* Reload is the same as load in this implementation */
513 return ( load() ); 506 return ( load() );
@@ -570,97 +563,85 @@ bool OPimContactAccessBackend_XML::load( const QString filename, bool isJournal
570 dict.insert( "BusinessState", new int(Qtopia::BusinessState) ); 563 dict.insert( "BusinessState", new int(Qtopia::BusinessState) );
571 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) ); 564 dict.insert( "BusinessZip", new int(Qtopia::BusinessZip) );
572 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) ); 565 dict.insert( "BusinessCountry", new int(Qtopia::BusinessCountry) );
573 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) ); 566 dict.insert( "BusinessWebPage", new int(Qtopia::BusinessWebPage) );
574 dict.insert( "JobTitle", new int(Qtopia::JobTitle) ); 567 dict.insert( "JobTitle", new int(Qtopia::JobTitle) );
575 dict.insert( "Department", new int(Qtopia::Department) ); 568 dict.insert( "Department", new int(Qtopia::Department) );
576 dict.insert( "Office", new int(Qtopia::Office) ); 569 dict.insert( "Office", new int(Qtopia::Office) );
577 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) ); 570 dict.insert( "BusinessPhone", new int(Qtopia::BusinessPhone) );
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;
659 */ 640 */
660 case JOURNALACTION: 641 case JOURNALACTION:
661 action = journal_action(it.data().toInt()); 642 action = journal_action(it.data().toInt());
662 foundAction = true; 643 foundAction = true;
663 owarn << "ODefBack(journal)::ACTION found: " << action << oendl; 644 owarn << "ODefBack(journal)::ACTION found: " << action << oendl;
664 break; 645 break;
665 case JOURNALROW: 646 case JOURNALROW:
666 journalKey = it.data().toInt(); 647 journalKey = it.data().toInt();
@@ -683,52 +664,50 @@ bool OPimContactAccessBackend_XML::load( const QString filename, bool isJournal
683 case ACTION_ADD: 664 case ACTION_ADD:
684 addContact_p (contact); 665 addContact_p (contact);
685 break; 666 break;
686 case ACTION_REMOVE: 667 case ACTION_REMOVE:
687 if ( !remove (contact.uid()) ) 668 if ( !remove (contact.uid()) )
688 owarn << "ODefBack(journal)::Unable to remove uid: " << contact.uid() << oendl; 669 owarn << "ODefBack(journal)::Unable to remove uid: " << contact.uid() << oendl;
689 break; 670 break;
690 case ACTION_REPLACE: 671 case ACTION_REPLACE:
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
727 // get a XML-File which is readable by our parser. 706 // get a XML-File which is readable by our parser.
728 // This is just a cheat, but better than rewrite the parser. 707 // This is just a cheat, but better than rewrite the parser.
729 if ( created ){ 708 if ( created ){
730 buf = "<Contacts>"; 709 buf = "<Contacts>";
731 QCString cstr = buf.utf8(); 710 QCString cstr = buf.utf8();
732 f.writeBlock( cstr.data(), cstr.length() ); 711 f.writeBlock( cstr.data(), cstr.length() );
733 } 712 }
734 713
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
@@ -41,58 +41,55 @@
41 41
42namespace Opie { 42namespace Opie {
43/* the default xml implementation */ 43/* the default xml implementation */
44/** 44/**
45 * This class is the XML implementation of a Contact backend 45 * This class is the XML implementation of a Contact backend
46 * it does implement everything available for OPimContact. 46 * it does implement everything available for OPimContact.
47 * @see OPimAccessBackend for more information of available methods 47 * @see OPimAccessBackend for more information of available methods
48 */ 48 */
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
91 88
92 void updateJournal( const OPimContact& cnt, journal_action action ); 89 void updateJournal( const OPimContact& cnt, journal_action action );
93 void removeJournal(); 90 void removeJournal();
94 91
95 protected: 92 protected:
96 bool m_changed; 93 bool m_changed;
97 QString m_journalName; 94 QString m_journalName;
98 QString m_fileName; 95 QString m_fileName;
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
@@ -15,202 +15,150 @@
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#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
@@ -21,101 +21,94 @@
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_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
@@ -146,50 +146,48 @@ void ODateBookAccessBackend_SQL::initFields()
146 for ( it = m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){ 146 for ( it = m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
147 m_reverseFieldMap.insert( it.data(), it.key() ); 147 m_reverseFieldMap.insert( it.data(), it.key() );
148 } 148 }
149 149
150} 150}
151 151
152bool ODateBookAccessBackend_SQL::load() 152bool ODateBookAccessBackend_SQL::load()
153{ 153{
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 );
188 if ( res.state() != OSQLResult::Success ){ 186 if ( res.state() != OSQLResult::Success ){
189 // m_uids.clear(); 187 // m_uids.clear();
190 return; 188 return;
191 } 189 }
192 190
193 m_uids = extractUids( res ); 191 m_uids = extractUids( res );
194 192
195} 193}
@@ -267,193 +265,184 @@ bool ODateBookAccessBackend_SQL::add( const OPimEvent& ev )
267 if ( !eventMap[it.key()].isEmpty() ) 265 if ( !eventMap[it.key()].isEmpty() )
268 qu += QString( ",\"%1\"" ).arg( eventMap[it.key()] ); 266 qu += QString( ",\"%1\"" ).arg( eventMap[it.key()] );
269 else 267 else
270 qu += QString( ",\"\"" ); 268 qu += QString( ",\"\"" );
271 } 269 }
272 qu += " );"; 270 qu += " );";
273 271
274 // Add custom entries 272 // Add custom entries
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{
308 QString qu = "DELETE from datebook where uid = " 305 QString qu = "DELETE from datebook where uid = "
309 + QString::number( uid ) + ";"; 306 + QString::number( uid ) + ";";
310 qu += "DELETE from custom_data where uid = " 307 qu += "DELETE from custom_data where uid = "
311 + QString::number( uid ) + ";"; 308 + QString::number( uid ) + ";";
312 309
313 OSQLRawQuery raw( qu ); 310 OSQLRawQuery raw( qu );
314 OSQLResult res = m_driver->query( &raw ); 311 OSQLResult res = m_driver->query( &raw );
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 (";
391 384
392 // Do it make sense to search other fields, too ? 385 // Do it make sense to search other fields, too ?
393 qu += " rlike(\""+ r.pattern() + "\", Location ) OR"; 386 qu += " rlike(\""+ r.pattern() + "\", Location ) OR";
394 qu += " rlike(\""+ r.pattern() + "\", Note )"; 387 qu += " rlike(\""+ r.pattern() + "\", Note )";
395 388
396 qu += " )"; 389 qu += " )";
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
@@ -45,54 +45,53 @@ namespace Opie {
45 * This is the default SQL implementation for DateBoook SQL storage 45 * This is the default SQL implementation for DateBoook SQL storage
46 * It fully implements the interface 46 * It fully implements the interface
47 * @see ODateBookAccessBackend 47 * @see ODateBookAccessBackend
48 * @see OPimAccessBackend 48 * @see OPimAccessBackend
49 */ 49 */
50class ODateBookAccessBackend_SQL : public ODateBookAccessBackend { 50class ODateBookAccessBackend_SQL : public ODateBookAccessBackend {
51public: 51public:
52 ODateBookAccessBackend_SQL( const QString& appName, 52 ODateBookAccessBackend_SQL( const QString& appName,
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();
91 90
92 QArray<int> extractUids( Opie::DB::OSQLResult& res ) const; 91 QArray<int> extractUids( Opie::DB::OSQLResult& res ) const;
93 QMap<QString, QString> requestCustom( int uid ) const; 92 QMap<QString, QString> requestCustom( int uid ) const;
94 93
95}; 94};
96 95
97} 96}
98 97
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
@@ -101,49 +101,48 @@ namespace {
101 FLocation, 101 FLocation,
102 FCategories, 102 FCategories,
103 FUid, 103 FUid,
104 FType, 104 FType,
105 FAlarm, 105 FAlarm,
106 FSound, 106 FSound,
107 FRType, 107 FRType,
108 FRWeekdays, 108 FRWeekdays,
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=\"";
142 if ( alarm.sound() == OPimAlarm::Loud ) 141 if ( alarm.sound() == OPimAlarm::Loud )
143 buf += "loud"; 142 buf += "loud";
144 else 143 else
145 buf += "silent"; 144 buf += "silent";
146 buf += "\""; 145 buf += "\"";
147 } 146 }
148 if ( ev.hasRecurrence() ) { 147 if ( ev.hasRecurrence() ) {
149 buf += ev.recurrence().toString(); 148 buf += ev.recurrence().toString();
@@ -305,84 +304,82 @@ OPimEvent ODateBookAccessBackend_XML::find( int uid ) const{
305 return m_raw[uid]; 304 return m_raw[uid];
306 else 305 else
307 return m_rep[uid]; 306 return m_rep[uid];
308} 307}
309bool ODateBookAccessBackend_XML::add( const OPimEvent& ev ) { 308bool ODateBookAccessBackend_XML::add( const OPimEvent& ev ) {
310 m_changed = true; 309 m_changed = true;
311 if (ev.hasRecurrence() ) 310 if (ev.hasRecurrence() )
312 m_rep.insert( ev.uid(), ev ); 311 m_rep.insert( ev.uid(), 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;
381 if ( ::fstat(fd, &attribute ) == -1 ) { 378 if ( ::fstat(fd, &attribute ) == -1 ) {
382 ::close( fd ); 379 ::close( fd );
383 return false; 380 return false;
384 } 381 }
385 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 382 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 );
386 if ( map_addr == ( (caddr_t)-1) ) { 383 if ( map_addr == ( (caddr_t)-1) ) {
387 ::close( fd ); 384 ::close( fd );
388 return false; 385 return false;
@@ -518,60 +515,58 @@ void ODateBookAccessBackend_XML::finalizeRecord( OPimEvent& ev ) {
518 ev.setStartDateTime( utc.toDateTime( start ) ); 515 ev.setStartDateTime( utc.toDateTime( start ) );
519 ev.setEndDateTime ( utc.toDateTime( end ) ); 516 ev.setEndDateTime ( utc.toDateTime( end ) );
520 }else { 517 }else {
521 /* to current date time */ 518 /* to current date time */
522 OPimTimeZone to_zone( ev.timeZone().isEmpty() ? OPimTimeZone::utc() : OPimTimeZone::current() ); 519 OPimTimeZone to_zone( ev.timeZone().isEmpty() ? OPimTimeZone::utc() : OPimTimeZone::current() );
523 520
524 ev.setStartDateTime(to_zone.toDateTime( start)); 521 ev.setStartDateTime(to_zone.toDateTime( start));
525 ev.setEndDateTime (to_zone.toDateTime( end)); 522 ev.setEndDateTime (to_zone.toDateTime( end));
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 );
570 } 565 }
571 break; 566 break;
572 case FAlarm: 567 case FAlarm:
573 alarmTime = value.toInt(); 568 alarmTime = value.toInt();
574 break; 569 break;
575 case FSound: 570 case FSound:
576 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; 571 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent;
577 break; 572 break;
@@ -613,49 +608,48 @@ void ODateBookAccessBackend_XML::setField( OPimEvent& e, int id, const QString&
613 case FREnd: { 608 case FREnd: {
614 end = ( (time_t) value.toLong() ); 609 end = ( (time_t) value.toLong() );
615 break; 610 break;
616 } 611 }
617 case FNote: 612 case FNote:
618 e.setNote( value ); 613 e.setNote( value );
619 break; 614 break;
620 case FCreated: 615 case FCreated:
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() );
654 uint arraycounter = 0; 648 uint arraycounter = 0;
655 QMap<int, OPimEvent>::ConstIterator it; 649 QMap<int, OPimEvent>::ConstIterator it;
656 650
657 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) 651 for ( it = m_raw.begin(); it != m_raw.end(); ++it )
658 if ( it.data().match( r ) ) 652 if ( it.data().match( r ) )
659 m_currentQuery[arraycounter++] = it.data().uid(); 653 m_currentQuery[arraycounter++] = it.data().uid();
660 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) 654 for ( it = m_rep.begin(); it != m_rep.end(); ++it )
661 if ( it.data().match( r ) ) 655 if ( it.data().match( r ) )
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
@@ -42,47 +42,47 @@ namespace Opie {
42 */ 42 */
43class ODateBookAccessBackend_XML : public ODateBookAccessBackend { 43class ODateBookAccessBackend_XML : public ODateBookAccessBackend {
44public: 44public:
45 ODateBookAccessBackend_XML( const QString& appName, 45 ODateBookAccessBackend_XML( const QString& appName,
46 const QString& fileName = QString::null); 46 const QString& fileName = QString::null);
47 ~ODateBookAccessBackend_XML(); 47 ~ODateBookAccessBackend_XML();
48 48
49 bool load(); 49 bool load();
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;
84}; 84};
85 85
86} 86}
87 87
88#endif 88#endif
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
@@ -13,184 +13,411 @@
13 .%`+i> _;_. 13 .%`+i> _;_.
14 .i_,=:_. -<s. This program is distributed in the hope that 14 .i_,=:_. -<s. This program is distributed in the hope that
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#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
@@ -7,35 +7,149 @@
7 _;:, .> :=|. This program is free software; you can 7 _;:, .> :=|. This program is free software; you can
8.> <`_, > . <= redistribute it and/or modify it under 8.> <`_, > . <= redistribute it and/or modify it under
9:`=1 )Y*s>-.-- : the terms of the GNU Library General Public 9:`=1 )Y*s>-.-- : the terms of the GNU Library General Public
10.="- .-=="i, .._ License as published by the Free Software 10.="- .-=="i, .._ License as published by the Free Software
11 - . .-<_> .<> Foundation; either version 2 of the License, 11 - . .-<_> .<> Foundation; either version 2 of the License,
12 ._= =} : or (at your option) any later version. 12 ._= =} : or (at your option) any later version.
13 .%`+i> _;_. 13 .%`+i> _;_.
14 .i_,=:_. -<s. This program is distributed in the hope that 14 .i_,=:_. -<s. This program is distributed in the hope that
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
@@ -18,42 +18,62 @@
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#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
@@ -434,257 +434,254 @@ bool OPimTodoAccessBackendSQL::load(){
434 434
435 m_dirty = true; 435 m_dirty = true;
436 return true; 436 return true;
437} 437}
438bool OPimTodoAccessBackendSQL::reload(){ 438bool OPimTodoAccessBackendSQL::reload(){
439 return load(); 439 return load();
440} 440}
441 441
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 )
683 to.setStartDate( startDate ); 680 to.setStartDate( startDate );
684 if ( hasCompletedDate ) 681 if ( hasCompletedDate )
685 to.setCompletedDate( completedDate ); 682 to.setCompletedDate( completedDate );
686 683
687 OPimNotifyManager& manager = to.notifiers(); 684 OPimNotifyManager& manager = to.notifiers();
688 manager.alarmsFromString( item.data("alarms") ); 685 manager.alarmsFromString( item.data("alarms") );
689 manager.remindersFromString( item.data("reminders") ); 686 manager.remindersFromString( item.data("reminders") );
690 687
@@ -696,200 +693,138 @@ OPimTodo OPimTodoAccessBackendSQL::todo( OSQLResultItem& item )const {
696 recMap.insert( OPimRecurrence::RType , item.data("RType") ); 693 recMap.insert( OPimRecurrence::RType , item.data("RType") );
697 recMap.insert( OPimRecurrence::RWeekdays , item.data("RWeekdays") ); 694 recMap.insert( OPimRecurrence::RWeekdays , item.data("RWeekdays") );
698 recMap.insert( OPimRecurrence::RPosition , item.data("RPosition") ); 695 recMap.insert( OPimRecurrence::RPosition , item.data("RPosition") );
699 recMap.insert( OPimRecurrence::RFreq , item.data("RFreq") ); 696 recMap.insert( OPimRecurrence::RFreq , item.data("RFreq") );
700 recMap.insert( OPimRecurrence::RHasEndDate, item.data("RHasEndDate") ); 697 recMap.insert( OPimRecurrence::RHasEndDate, item.data("RHasEndDate") );
701 recMap.insert( OPimRecurrence::EndDate , item.data("EndDate") ); 698 recMap.insert( OPimRecurrence::EndDate , item.data("EndDate") );
702 recMap.insert( OPimRecurrence::Created , item.data("Created") ); 699 recMap.insert( OPimRecurrence::Created , item.data("Created") );
703 recMap.insert( OPimRecurrence::Exceptions , item.data("Exceptions") ); 700 recMap.insert( OPimRecurrence::Exceptions , item.data("Exceptions") );
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
@@ -30,64 +30,59 @@
30#define OPIE_PIM_ACCESS_SQL_H 30#define OPIE_PIM_ACCESS_SQL_H
31 31
32/* #include <qasciidict.h> */ 32/* #include <qasciidict.h> */
33 33
34#include <opie2/otodoaccessbackend.h> 34#include <opie2/otodoaccessbackend.h>
35 35
36namespace Opie { 36namespace Opie {
37namespace DB { 37namespace 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
@@ -71,49 +71,48 @@ namespace {
71 if( ( ob = isAPropertyOf( obj, VCStatusProp )) != 0 ){ 71 if( ( ob = isAPropertyOf( obj, VCStatusProp )) != 0 ){
72 name = vObjectStringZValue( ob ); 72 name = vObjectStringZValue( ob );
73 if( name == "COMPLETED" ){ 73 if( name == "COMPLETED" ){
74 event.setCompleted( true ); 74 event.setCompleted( true );
75 }else{ 75 }else{
76 event.setCompleted( false ); 76 event.setCompleted( false );
77 } 77 }
78 }else 78 }else
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 }
112 111
113 if( event.isCompleted() ) 112 if( event.isCompleted() )
114 addPropValue( task, VCStatusProp, "COMPLETED"); 113 addPropValue( task, VCStatusProp, "COMPLETED");
115 114
116 QString string = QString::number(event.priority() ); 115 QString string = QString::number(event.priority() );
117 addPropValue( task, VCPriorityProp, string.local8Bit() ); 116 addPropValue( task, VCPriorityProp, string.local8Bit() );
118 117
119 addPropValue( task, VCCategoriesProp, 118 addPropValue( task, VCCategoriesProp,
@@ -212,78 +211,49 @@ void OPimTodoAccessVCal::clear() {
212bool OPimTodoAccessVCal::add( const OPimTodo& to ) { 211bool OPimTodoAccessVCal::add( const OPimTodo& to ) {
213 m_map.insert( to.uid(), to ); 212 m_map.insert( to.uid(), to );
214 m_dirty = true; 213 m_dirty = true;
215 return true; 214 return true;
216} 215}
217bool OPimTodoAccessVCal::remove( int uid ) { 216bool OPimTodoAccessVCal::remove( int uid ) {
218 m_map.remove( uid ); 217 m_map.remove( uid );
219 m_dirty = true; 218 m_dirty = true;
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
@@ -22,51 +22,45 @@
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_OTODO_ACCESS_VCAL_H 29#ifndef OPIE_OTODO_ACCESS_VCAL_H
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
@@ -13,50 +13,53 @@
13 .%`+i> _;_. 13 .%`+i> _;_.
14 .i_,=:_. -<s. This program is distributed in the hope that 14 .i_,=:_. -<s. This program is distributed in the hope that
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/* 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
55#include <unistd.h> 58#include <unistd.h>
56 59
57 60
58using namespace Opie; 61using namespace Opie;
59 62
60namespace { 63namespace {
61 time_t rp_end; 64 time_t rp_end;
62 OPimRecurrence* rec; 65 OPimRecurrence* rec;
@@ -121,89 +124,87 @@ bool OPimTodoAccessXML::load() {
121 m_changed = false; 124 m_changed = false;
122 /* initialize dict */ 125 /* initialize dict */
123 /* 126 /*
124 * UPDATE dict if you change anything!!! 127 * UPDATE dict if you change anything!!!
125 */ 128 */
126 QAsciiDict<int> dict(26); 129 QAsciiDict<int> dict(26);
127 dict.setAutoDelete( TRUE ); 130 dict.setAutoDelete( TRUE );
128 dict.insert("Categories" , new int(OPimTodo::Category) ); 131 dict.insert("Categories" , new int(OPimTodo::Category) );
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
162 if ( fstat(fd, &attribut ) == -1 ) { 164 if ( fstat(fd, &attribut ) == -1 ) {
163 ::close( fd ); 165 ::close( fd );
164 return false; 166 return false;
165 } 167 }
166 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 168 void* map_addr = ::mmap(NULL, attribut.st_size, PROT_READ, MAP_SHARED, fd, 0 );
167 if ( map_addr == ( (caddr_t)-1) ) { 169 if ( map_addr == ( (caddr_t)-1) ) {
168 ::close(fd ); 170 ::close(fd );
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
202 i = ++j; // skip = 203 i = ++j; // skip =
203 204
204 // find the start of quotes 205 // find the start of quotes
205 while ( i < len && dt[i] != '"' ) 206 while ( i < len && dt[i] != '"' )
206 ++i; 207 ++i;
207 j = ++i; 208 j = ++i;
208 209
209 bool haveUtf = FALSE; 210 bool haveUtf = FALSE;
@@ -217,226 +218,214 @@ bool OPimTodoAccessXML::load() {
217 } 218 }
218 if ( i == j ) { 219 if ( i == j ) {
219 // empty value 220 // empty value
220 i = j + 1; 221 i = j + 1;
221 continue; 222 continue;
222 } 223 }
223 224
224 QCString value( dt+i, j-i+1 ); 225 QCString value( dt+i, j-i+1 );
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();
291 written = f.writeBlock( cstr.data(), cstr.length() ); 288 written = f.writeBlock( cstr.data(), cstr.length() );
292 289
293 /* less written then we wanted */ 290 /* less written then we wanted */
294 if ( written != (int)cstr.length() ) { 291 if ( written != (int)cstr.length() ) {
295 f.close(); 292 f.close();
296 QFile::remove( strNewFile ); 293 QFile::remove( strNewFile );
297 return false; 294 return false;
298 } 295 }
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() );
435 break; 424 break;
436 case OPimTodo::Description: 425 case OPimTodo::Description:
437 ev.setDescription( val ); 426 ev.setDescription( val );
438 break; 427 break;
439 case OPimTodo::Summary: 428 case OPimTodo::Summary:
440 ev.setSummary( val ); 429 ev.setSummary( val );
441 break; 430 break;
442 case OPimTodo::Priority: 431 case OPimTodo::Priority:
@@ -447,50 +436,48 @@ void OPimTodoAccessXML::todo( QAsciiDict<int>* dict, OPimTodo& ev,
447 break; 436 break;
448 case OPimTodo::DateMonth: 437 case OPimTodo::DateMonth:
449 m_month = val.toInt(); 438 m_month = val.toInt();
450 break; 439 break;
451 case OPimTodo::DateYear: 440 case OPimTodo::DateYear:
452 m_year = val.toInt(); 441 m_year = val.toInt();
453 break; 442 break;
454 case OPimTodo::Progress: 443 case OPimTodo::Progress:
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 {
489 /* 476 /*
490 * A cross refernce looks like 477 * A cross refernce looks like
491 * appname,id;appname,id 478 * appname,id;appname,id
492 * we need to split it up 479 * we need to split it up
493 */ 480 */
494 QStringList refs = QStringList::split(';', val ); 481 QStringList refs = QStringList::split(';', val );
495 QStringList::Iterator strIt; 482 QStringList::Iterator strIt;
496 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) { 483 for (strIt = refs.begin(); strIt != refs.end(); ++strIt ) {
@@ -521,394 +508,213 @@ void OPimTodoAccessXML::todo( QAsciiDict<int>* dict, OPimTodo& ev,
521 break; 508 break;
522 case FRPosition: 509 case FRPosition:
523 recur()->setPosition( val.toInt() ); 510 recur()->setPosition( val.toInt() );
524 break; 511 break;
525 case FRFreq: 512 case FRFreq:
526 recur()->setFrequency( val.toInt() ); 513 recur()->setFrequency( val.toInt() );
527 break; 514 break;
528 case FRHasEndDate: 515 case FRHasEndDate:
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
595 if ( ev.hasRecurrence() ) { 579 if ( ev.hasRecurrence() ) {
596 str += ev.recurrence().toString(); 580 str += ev.recurrence().toString();
597 } 581 }
598 if ( ev.hasStartDate() ) 582 if ( ev.hasStartDate() )
599 str += "StartDate=\""+ OPimDateConversion::dateToString( ev.startDate() ) +"\" "; 583 str += "StartDate=\""+ OPimDateConversion::dateToString( ev.startDate() ) +"\" ";
600 if ( ev.hasCompletedDate() ) 584 if ( ev.hasCompletedDate() )
601 str += "CompletedDate=\""+ OPimDateConversion::dateToString( ev.completedDate() ) +"\" "; 585 str += "CompletedDate=\""+ OPimDateConversion::dateToString( ev.completedDate() ) +"\" ";
602 if ( ev.hasState() ) 586 if ( ev.hasState() )
603 str += "State=\""+QString::number( ev.state().state() )+"\" "; 587 str += "State=\""+QString::number( ev.state().state() )+"\" ";
604 588
605 /* 589 /*
606 * save reminders and notifiers! 590 * save reminders and notifiers!
607 * DATE_TIME:DURATION:SOUND:NOT_USED_YET;OTHER_DATE_TIME:OTHER_DURATION:SOUND:.... 591 * DATE_TIME:DURATION:SOUND:NOT_USED_YET;OTHER_DATE_TIME:OTHER_DURATION:SOUND:....
608 */ 592 */
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
@@ -42,48 +42,47 @@ public:
42 /** 42 /**
43 * fileName if Empty we will use the default path 43 * fileName if Empty we will use the default path
44 */ 44 */
45 OPimTodoAccessXML( const QString& appName, 45 OPimTodoAccessXML( const QString& appName,
46 const QString& fileName = QString::null ); 46 const QString& fileName = QString::null );
47 ~OPimTodoAccessXML(); 47 ~OPimTodoAccessXML();
48 48
49 bool load(); 49 bool load();
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