summaryrefslogtreecommitdiff
authoreilers <eilers>2003-12-08 15:18:10 (UTC)
committer eilers <eilers>2003-12-08 15:18:10 (UTC)
commit6974a4bbdc674a2a5d41d801f80035a183faedb5 (patch) (unidiff)
tree09a719ef263047e92ffb866da13168b7f7d41f23
parent7f2f736597490fd1592d7ed1f40e4abf824673c0 (diff)
downloadopie-6974a4bbdc674a2a5d41d801f80035a183faedb5.zip
opie-6974a4bbdc674a2a5d41d801f80035a183faedb5.tar.gz
opie-6974a4bbdc674a2a5d41d801f80035a183faedb5.tar.bz2
Committing unfinished sql implementation before merging to libopie2 starts..
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--libopie/pim/ocontactaccessbackend_sql.cpp11
-rw-r--r--libopie/pim/ocontactaccessbackend_sql.h5
-rw-r--r--libopie/pim/odatebookaccessbackend_sql.cpp221
-rw-r--r--libopie/pim/odatebookaccessbackend_sql.h60
-rw-r--r--libopie/pim/odatebookaccessbackend_xml.cpp12
-rw-r--r--libopie/pim/oevent.cpp131
-rw-r--r--libopie/pim/oevent.h38
-rw-r--r--libopie/pim/orecur.cpp8
-rw-r--r--libopie/pim/orecur.h1
-rw-r--r--libopie/pim/otodoaccesssql.cpp5
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp11
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_sql.h5
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp221
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_sql.h60
-rw-r--r--libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp12
-rw-r--r--libopie2/opiepim/backend/otodoaccesssql.cpp5
-rw-r--r--libopie2/opiepim/core/orecur.cpp8
-rw-r--r--libopie2/opiepim/core/orecur.h1
-rw-r--r--libopie2/opiepim/oevent.cpp131
-rw-r--r--libopie2/opiepim/oevent.h38
20 files changed, 942 insertions, 42 deletions
diff --git a/libopie/pim/ocontactaccessbackend_sql.cpp b/libopie/pim/ocontactaccessbackend_sql.cpp
index 132c9fc..dd9dbde 100644
--- a/libopie/pim/ocontactaccessbackend_sql.cpp
+++ b/libopie/pim/ocontactaccessbackend_sql.cpp
@@ -1,734 +1,743 @@
1/* 1/*
2 * SQL Backend for the OPIE-Contact Database. 2 * SQL Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * 5 *
6 * ===================================================================== 6 * =====================================================================
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * ===================================================================== 11 * =====================================================================
12 * ===================================================================== 12 * =====================================================================
13 * Version: $Id$ 13 * Version: $Id$
14 * ===================================================================== 14 * =====================================================================
15 * History: 15 * History:
16 * $Log$ 16 * $Log$
17 * Revision 1.3 2003/12/08 15:18:10 eilers
18 * Committing unfinished sql implementation before merging to libopie2 starts..
19 *
17 * Revision 1.2 2003/09/29 07:44:26 eilers 20 * Revision 1.2 2003/09/29 07:44:26 eilers
18 * Improvement of PIM-SQL Databases, but search queries are still limited. 21 * Improvement of PIM-SQL Databases, but search queries are still limited.
19 * Addressbook: Changed table layout. Now, we just need 1/3 of disk-space. 22 * Addressbook: Changed table layout. Now, we just need 1/3 of disk-space.
20 * Todo: Started to add new attributes. Some type conversions missing. 23 * Todo: Started to add new attributes. Some type conversions missing.
21 * 24 *
22 * Revision 1.1 2003/09/22 14:31:16 eilers 25 * Revision 1.1 2003/09/22 14:31:16 eilers
23 * Added first experimental incarnation of sql-backend for addressbook. 26 * Added first experimental incarnation of sql-backend for addressbook.
24 * Some modifications to be able to compile the todo sql-backend. 27 * Some modifications to be able to compile the todo sql-backend.
25 * A lot of changes fill follow... 28 * A lot of changes fill follow...
26 * 29 *
27 */ 30 */
28 31
29#include "ocontactaccessbackend_sql.h" 32#include "ocontactaccessbackend_sql.h"
30 33
31#include <qarray.h> 34#include <qarray.h>
32#include <qdatetime.h> 35#include <qdatetime.h>
33#include <qstringlist.h> 36#include <qstringlist.h>
34 37
35#include <qpe/global.h> 38#include <qpe/global.h>
36#include <qpe/recordfields.h> 39#include <qpe/recordfields.h>
37 40
38#include <opie/ocontactfields.h> 41#include <opie/ocontactfields.h>
39#include <opie/oconversion.h> 42#include <opie/oconversion.h>
40#include <opie2/osqldriver.h> 43#include <opie2/osqldriver.h>
41#include <opie2/osqlresult.h> 44#include <opie2/osqlresult.h>
42#include <opie2/osqlmanager.h> 45#include <opie2/osqlmanager.h>
43#include <opie2/osqlquery.h> 46#include <opie2/osqlquery.h>
44 47
45 48
46 49
47 50
48// If defined, we use a horizontal table ( uid, attr1, attr2, attr3, ..., attrn ) instead 51// If defined, we use a horizontal table ( uid, attr1, attr2, attr3, ..., attrn ) instead
49// vertical like "uid, type, value". 52// vertical like "uid, type, value".
50// DON'T DEACTIVATE THIS DEFINE IN PRODUCTIVE ENVIRONMENTS !! 53// DON'T DEACTIVATE THIS DEFINE IN PRODUCTIVE ENVIRONMENTS !!
51#define __STORE_HORIZONTAL_ 54#define __STORE_HORIZONTAL_
52 55
53// Distinct loading is not very fast. If I expect that every person has just 56// Distinct loading is not very fast. If I expect that every person has just
54// one (and always one) 'Last Name', I can request all uid's for existing lastnames, 57// one (and always one) 'Last Name', I can request all uid's for existing lastnames,
55// which is faster.. 58// which is faster..
56// But this may not be true for all entries, like company contacts.. 59// But this may not be true for all entries, like company contacts..
57// The current AddressBook application handles this problem, but other may not.. (eilers) 60// The current AddressBook application handles this problem, but other may not.. (eilers)
58#define __USE_SUPERFAST_LOADQUERY 61#define __USE_SUPERFAST_LOADQUERY
59 62
60 63
61/* 64/*
62 * Implementation of used query types 65 * Implementation of used query types
63 * CREATE query 66 * CREATE query
64 * LOAD query 67 * LOAD query
65 * INSERT 68 * INSERT
66 * REMOVE 69 * REMOVE
67 * CLEAR 70 * CLEAR
68 */ 71 */
69namespace { 72namespace {
70 /** 73 /**
71 * CreateQuery for the Todolist Table 74 * CreateQuery for the Todolist Table
72 */ 75 */
73 class CreateQuery : public OSQLQuery { 76 class CreateQuery : public OSQLQuery {
74 public: 77 public:
75 CreateQuery(); 78 CreateQuery();
76 ~CreateQuery(); 79 ~CreateQuery();
77 QString query()const; 80 QString query()const;
78 }; 81 };
79 82
80 /** 83 /**
81 * Clears (delete) a Table 84 * Clears (delete) a Table
82 */ 85 */
83 class ClearQuery : public OSQLQuery { 86 class ClearQuery : public OSQLQuery {
84 public: 87 public:
85 ClearQuery(); 88 ClearQuery();
86 ~ClearQuery(); 89 ~ClearQuery();
87 QString query()const; 90 QString query()const;
88 91
89 }; 92 };
90 93
91 94
92 /** 95 /**
93 * LoadQuery 96 * LoadQuery
94 * this one queries for all uids 97 * this one queries for all uids
95 */ 98 */
96 class LoadQuery : public OSQLQuery { 99 class LoadQuery : public OSQLQuery {
97 public: 100 public:
98 LoadQuery(); 101 LoadQuery();
99 ~LoadQuery(); 102 ~LoadQuery();
100 QString query()const; 103 QString query()const;
101 }; 104 };
102 105
103 /** 106 /**
104 * inserts/adds a OContact to the table 107 * inserts/adds a OContact to the table
105 */ 108 */
106 class InsertQuery : public OSQLQuery { 109 class InsertQuery : public OSQLQuery {
107 public: 110 public:
108 InsertQuery(const OContact& ); 111 InsertQuery(const OContact& );
109 ~InsertQuery(); 112 ~InsertQuery();
110 QString query()const; 113 QString query()const;
111 private: 114 private:
112 OContact m_contact; 115 OContact m_contact;
113 }; 116 };
114 117
115 118
116 /** 119 /**
117 * removes one from the table 120 * removes one from the table
118 */ 121 */
119 class RemoveQuery : public OSQLQuery { 122 class RemoveQuery : public OSQLQuery {
120 public: 123 public:
121 RemoveQuery(int uid ); 124 RemoveQuery(int uid );
122 ~RemoveQuery(); 125 ~RemoveQuery();
123 QString query()const; 126 QString query()const;
124 private: 127 private:
125 int m_uid; 128 int m_uid;
126 }; 129 };
127 130
128 /** 131 /**
129 * a find query for noncustom elements 132 * a find query for noncustom elements
130 */ 133 */
131 class FindQuery : public OSQLQuery { 134 class FindQuery : public OSQLQuery {
132 public: 135 public:
133 FindQuery(int uid); 136 FindQuery(int uid);
134 FindQuery(const QArray<int>& ); 137 FindQuery(const QArray<int>& );
135 ~FindQuery(); 138 ~FindQuery();
136 QString query()const; 139 QString query()const;
137 private: 140 private:
138 QString single()const; 141 QString single()const;
139 QString multi()const; 142 QString multi()const;
140 QArray<int> m_uids; 143 QArray<int> m_uids;
141 int m_uid; 144 int m_uid;
142 }; 145 };
143 146
144 /** 147 /**
145 * a find query for custom elements 148 * a find query for custom elements
146 */ 149 */
147 class FindCustomQuery : public OSQLQuery { 150 class FindCustomQuery : public OSQLQuery {
148 public: 151 public:
149 FindCustomQuery(int uid); 152 FindCustomQuery(int uid);
150 FindCustomQuery(const QArray<int>& ); 153 FindCustomQuery(const QArray<int>& );
151 ~FindCustomQuery(); 154 ~FindCustomQuery();
152 QString query()const; 155 QString query()const;
153 private: 156 private:
154 QString single()const; 157 QString single()const;
155 QString multi()const; 158 QString multi()const;
156 QArray<int> m_uids; 159 QArray<int> m_uids;
157 int m_uid; 160 int m_uid;
158 }; 161 };
159 162
160 163
161 164
162 // We using three tables to store the information: 165 // We using three tables to store the information:
163 // 1. addressbook : It contains General information about the contact (non custom) 166 // 1. addressbook : It contains General information about the contact (non custom)
164 // 2. custom_data : Not official supported entries 167 // 2. custom_data : Not official supported entries
165 // All tables are connected by the uid of the contact. 168 // All tables are connected by the uid of the contact.
166 // Maybe I should add a table for meta-information ? 169 // Maybe I should add a table for meta-information ?
167 CreateQuery::CreateQuery() : OSQLQuery() {} 170 CreateQuery::CreateQuery() : OSQLQuery() {}
168 CreateQuery::~CreateQuery() {} 171 CreateQuery::~CreateQuery() {}
169 QString CreateQuery::query()const { 172 QString CreateQuery::query()const {
170 QString qu; 173 QString qu;
171#ifdef __STORE_HORIZONTAL_ 174#ifdef __STORE_HORIZONTAL_
172 175
173 qu += "create table addressbook( uid PRIMARY KEY "; 176 qu += "create table addressbook( uid PRIMARY KEY ";
174 177
175 QStringList fieldList = OContactFields::untrfields( false ); 178 QStringList fieldList = OContactFields::untrfields( false );
176 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 179 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
177 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( *it ); 180 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( *it );
178 } 181 }
179 qu += " );"; 182 qu += " );";
180 183
181 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );"; 184 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
182 185
183#else 186#else
184 187
185 qu += "create table addressbook( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id));"; 188 qu += "create table addressbook( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id));";
186 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );"; 189 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
187 // qu += "create table dates( uid PRIMARY KEY, type, day, month, year, hour, minute, second );"; 190 // qu += "create table dates( uid PRIMARY KEY, type, day, month, year, hour, minute, second );";
188 191
189#endif // __STORE_HORIZONTAL_ 192#endif // __STORE_HORIZONTAL_
190 return qu; 193 return qu;
191 } 194 }
192 195
193 ClearQuery::ClearQuery() 196 ClearQuery::ClearQuery()
194 : OSQLQuery() {} 197 : OSQLQuery() {}
195 ClearQuery::~ClearQuery() {} 198 ClearQuery::~ClearQuery() {}
196 QString ClearQuery::query()const { 199 QString ClearQuery::query()const {
197 QString qu = "drop table addressbook;"; 200 QString qu = "drop table addressbook;";
198 qu += "drop table custom_data;"; 201 qu += "drop table custom_data;";
199 // qu += "drop table dates;"; 202 // qu += "drop table dates;";
200 return qu; 203 return qu;
201 } 204 }
202 205
203 206
204 LoadQuery::LoadQuery() : OSQLQuery() {} 207 LoadQuery::LoadQuery() : OSQLQuery() {}
205 LoadQuery::~LoadQuery() {} 208 LoadQuery::~LoadQuery() {}
206 QString LoadQuery::query()const { 209 QString LoadQuery::query()const {
207 QString qu; 210 QString qu;
208#ifdef __STORE_HORIZONTAL_ 211#ifdef __STORE_HORIZONTAL_
209 qu += "select uid from addressbook"; 212 qu += "select uid from addressbook";
210#else 213#else
211# ifndef __USE_SUPERFAST_LOADQUERY 214# ifndef __USE_SUPERFAST_LOADQUERY
212 qu += "select distinct uid from addressbook"; 215 qu += "select distinct uid from addressbook";
213# else 216# else
214 qu += "select uid from addressbook where type = 'Last Name'"; 217 qu += "select uid from addressbook where type = 'Last Name'";
215# endif // __USE_SUPERFAST_LOADQUERY 218# endif // __USE_SUPERFAST_LOADQUERY
216#endif // __STORE_HORIZONTAL_ 219#endif // __STORE_HORIZONTAL_
217 220
218 return qu; 221 return qu;
219 } 222 }
220 223
221 224
222 InsertQuery::InsertQuery( const OContact& contact ) 225 InsertQuery::InsertQuery( const OContact& contact )
223 : OSQLQuery(), m_contact( contact ) { 226 : OSQLQuery(), m_contact( contact ) {
224 } 227 }
225 228
226 InsertQuery::~InsertQuery() { 229 InsertQuery::~InsertQuery() {
227 } 230 }
228 231
229 /* 232 /*
230 * converts from a OContact to a query 233 * converts from a OContact to a query
231 */ 234 */
232 QString InsertQuery::query()const{ 235 QString InsertQuery::query()const{
233 236
234#ifdef __STORE_HORIZONTAL_ 237#ifdef __STORE_HORIZONTAL_
235 QString qu; 238 QString qu;
236 qu += "insert into addressbook VALUES( " + 239 qu += "insert into addressbook VALUES( " +
237 QString::number( m_contact.uid() ); 240 QString::number( m_contact.uid() );
238 241
239 // Get all information out of the contact-class 242 // Get all information out of the contact-class
240 // Remember: The category is stored in contactMap, too ! 243 // Remember: The category is stored in contactMap, too !
241 QMap<int, QString> contactMap = m_contact.toMap(); 244 QMap<int, QString> contactMap = m_contact.toMap();
242 245
243 QStringList fieldList = OContactFields::untrfields( false ); 246 QStringList fieldList = OContactFields::untrfields( false );
244 QMap<QString, int> translate = OContactFields::untrFieldsToId(); 247 QMap<QString, int> translate = OContactFields::untrFieldsToId();
245 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 248 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
246 // Convert Column-String to Id and get value for this id.. 249 // Convert Column-String to Id and get value for this id..
247 // Hmmm.. Maybe not very cute solution.. 250 // Hmmm.. Maybe not very cute solution..
248 int id = translate[*it]; 251 int id = translate[*it];
249 switch ( id ){ 252 switch ( id ){
250 case Qtopia::Birthday:{ 253 case Qtopia::Birthday:{
251 // These entries should stored in a special format 254 // These entries should stored in a special format
252 // year-month-day 255 // year-month-day
253 QDate day = m_contact.birthday(); 256 QDate day = m_contact.birthday();
254 if ( day.isValid() ){ 257 if ( day.isValid() ){
255 qu += QString(",\"%1-%2-%3\"") 258 qu += QString(",\"%1-%2-%3\"")
256 .arg( day.year() ) 259 .arg( day.year() )
257 .arg( day.month() ) 260 .arg( day.month() )
258 .arg( day.day() ); 261 .arg( day.day() );
259 } else { 262 } else {
260 qu += ",\"\""; 263 qu += ",\"\"";
261 } 264 }
262 } 265 }
263 break; 266 break;
264 case Qtopia::Anniversary:{ 267 case Qtopia::Anniversary:{
265 // These entries should stored in a special format 268 // These entries should stored in a special format
266 // year-month-day 269 // year-month-day
267 QDate day = m_contact.anniversary(); 270 QDate day = m_contact.anniversary();
268 if ( day.isValid() ){ 271 if ( day.isValid() ){
269 qu += QString(",\"%1-%2-%3\"") 272 qu += QString(",\"%1-%2-%3\"")
270 .arg( day.year() ) 273 .arg( day.year() )
271 .arg( day.month() ) 274 .arg( day.month() )
272 .arg( day.day() ); 275 .arg( day.day() );
273 } else { 276 } else {
274 qu += ",\"\""; 277 qu += ",\"\"";
275 } 278 }
276 } 279 }
277 break; 280 break;
278 281
279 default: 282 default:
280 qu += QString( ",\"%1\"" ).arg( contactMap[id] ); 283 qu += QString( ",\"%1\"" ).arg( contactMap[id] );
281 } 284 }
282 } 285 }
283 qu += " );"; 286 qu += " );";
284 287
285 288
286#else 289#else
287 // Get all information out of the contact-class 290 // Get all information out of the contact-class
288 // Remember: The category is stored in contactMap, too ! 291 // Remember: The category is stored in contactMap, too !
289 QMap<int, QString> contactMap = m_contact.toMap(); 292 QMap<int, QString> contactMap = m_contact.toMap();
290 293
291 QMap<QString, QString> addressbook_db; 294 QMap<QString, QString> addressbook_db;
292 295
293 // Get the translation from the ID to the String 296 // Get the translation from the ID to the String
294 QMap<int, QString> transMap = OContactFields::idToUntrFields(); 297 QMap<int, QString> transMap = OContactFields::idToUntrFields();
295 298
296 for( QMap<int, QString>::Iterator it = contactMap.begin(); 299 for( QMap<int, QString>::Iterator it = contactMap.begin();
297 it != contactMap.end(); ++it ){ 300 it != contactMap.end(); ++it ){
298 switch ( it.key() ){ 301 switch ( it.key() ){
299 case Qtopia::Birthday:{ 302 case Qtopia::Birthday:{
300 // These entries should stored in a special format 303 // These entries should stored in a special format
301 // year-month-day 304 // year-month-day
302 QDate day = m_contact.birthday(); 305 QDate day = m_contact.birthday();
303 addressbook_db.insert( transMap[it.key()], 306 addressbook_db.insert( transMap[it.key()],
304 QString("%1-%2-%3") 307 QString("%1-%2-%3")
305 .arg( day.year() ) 308 .arg( day.year() )
306 .arg( day.month() ) 309 .arg( day.month() )
307 .arg( day.day() ) ); 310 .arg( day.day() ) );
308 } 311 }
309 break; 312 break;
310 case Qtopia::Anniversary:{ 313 case Qtopia::Anniversary:{
311 // These entries should stored in a special format 314 // These entries should stored in a special format
312 // year-month-day 315 // year-month-day
313 QDate day = m_contact.anniversary(); 316 QDate day = m_contact.anniversary();
314 addressbook_db.insert( transMap[it.key()], 317 addressbook_db.insert( transMap[it.key()],
315 QString("%1-%2-%3") 318 QString("%1-%2-%3")
316 .arg( day.year() ) 319 .arg( day.year() )
317 .arg( day.month() ) 320 .arg( day.month() )
318 .arg( day.day() ) ); 321 .arg( day.day() ) );
319 } 322 }
320 break; 323 break;
321 case Qtopia::AddressUid: // Ignore UID 324 case Qtopia::AddressUid: // Ignore UID
322 break; 325 break;
323 default: // Translate id to String 326 default: // Translate id to String
324 addressbook_db.insert( transMap[it.key()], it.data() ); 327 addressbook_db.insert( transMap[it.key()], it.data() );
325 break; 328 break;
326 } 329 }
327 330
328 } 331 }
329 332
330 // Now convert this whole stuff into a SQL String, beginning with 333 // Now convert this whole stuff into a SQL String, beginning with
331 // the addressbook table.. 334 // the addressbook table..
332 QString qu; 335 QString qu;
333 // qu += "begin transaction;"; 336 // qu += "begin transaction;";
334 int id = 0; 337 int id = 0;
335 for( QMap<QString, QString>::Iterator it = addressbook_db.begin(); 338 for( QMap<QString, QString>::Iterator it = addressbook_db.begin();
336 it != addressbook_db.end(); ++it ){ 339 it != addressbook_db.end(); ++it ){
337 qu += "insert into addressbook VALUES(" 340 qu += "insert into addressbook VALUES("
338 + QString::number( m_contact.uid() ) 341 + QString::number( m_contact.uid() )
339 + "," 342 + ","
340 + QString::number( id++ ) 343 + QString::number( id++ )
341 + ",'" 344 + ",'"
342 + it.key() //.latin1() 345 + it.key() //.latin1()
343 + "'," 346 + "',"
344 + "0" // Priority for future enhancements 347 + "0" // Priority for future enhancements
345 + ",'" 348 + ",'"
346 + it.data() //.latin1() 349 + it.data() //.latin1()
347 + "');"; 350 + "');";
348 } 351 }
349 352
350 #endif //__STORE_HORIZONTAL_ 353 #endif //__STORE_HORIZONTAL_
351 // Now add custom data.. 354 // Now add custom data..
352#ifdef __STORE_HORIZONTAL_ 355#ifdef __STORE_HORIZONTAL_
353 int id = 0; 356 int id = 0;
354#endif 357#endif
355 id = 0; 358 id = 0;
356 QMap<QString, QString> customMap = m_contact.toExtraMap(); 359 QMap<QString, QString> customMap = m_contact.toExtraMap();
357 for( QMap<QString, QString>::Iterator it = customMap.begin(); 360 for( QMap<QString, QString>::Iterator it = customMap.begin();
358 it != customMap.end(); ++it ){ 361 it != customMap.end(); ++it ){
359 qu += "insert into custom_data VALUES(" 362 qu += "insert into custom_data VALUES("
360 + QString::number( m_contact.uid() ) 363 + QString::number( m_contact.uid() )
361 + "," 364 + ","
362 + QString::number( id++ ) 365 + QString::number( id++ )
363 + ",'" 366 + ",'"
364 + it.key() //.latin1() 367 + it.key() //.latin1()
365 + "'," 368 + "',"
366 + "0" // Priority for future enhancements 369 + "0" // Priority for future enhancements
367 + ",'" 370 + ",'"
368 + it.data() //.latin1() 371 + it.data() //.latin1()
369 + "');"; 372 + "');";
370 } 373 }
371 // qu += "commit;"; 374 // qu += "commit;";
372 qWarning("add %s", qu.latin1() ); 375 qWarning("add %s", qu.latin1() );
373 return qu; 376 return qu;
374 } 377 }
375 378
376 379
377 RemoveQuery::RemoveQuery(int uid ) 380 RemoveQuery::RemoveQuery(int uid )
378 : OSQLQuery(), m_uid( uid ) {} 381 : OSQLQuery(), m_uid( uid ) {}
379 RemoveQuery::~RemoveQuery() {} 382 RemoveQuery::~RemoveQuery() {}
380 QString RemoveQuery::query()const { 383 QString RemoveQuery::query()const {
381 QString qu = "DELETE from addressbook where uid = " 384 QString qu = "DELETE from addressbook where uid = "
382 + QString::number(m_uid) + ";"; 385 + QString::number(m_uid) + ";";
383 qu += "DELETE from custom_data where uid = " 386 qu += "DELETE from custom_data where uid = "
384 + QString::number(m_uid) + ";"; 387 + QString::number(m_uid) + ";";
385 return qu; 388 return qu;
386 } 389 }
387 390
388 391
389 392
390 393
391 FindQuery::FindQuery(int uid) 394 FindQuery::FindQuery(int uid)
392 : OSQLQuery(), m_uid( uid ) { 395 : OSQLQuery(), m_uid( uid ) {
393 } 396 }
394 FindQuery::FindQuery(const QArray<int>& ints) 397 FindQuery::FindQuery(const QArray<int>& ints)
395 : OSQLQuery(), m_uids( ints ){ 398 : OSQLQuery(), m_uids( ints ){
396 } 399 }
397 FindQuery::~FindQuery() { 400 FindQuery::~FindQuery() {
398 } 401 }
399 QString FindQuery::query()const{ 402 QString FindQuery::query()const{
400 // if ( m_uids.count() == 0 ) 403 // if ( m_uids.count() == 0 )
401 return single(); 404 return single();
402 } 405 }
403 /* 406 /*
404 else 407 else
405 return multi(); 408 return multi();
406 } 409 }
407 QString FindQuery::multi()const { 410 QString FindQuery::multi()const {
408 QString qu = "select uid, type, value from addressbook where"; 411 QString qu = "select uid, type, value from addressbook where";
409 for (uint i = 0; i < m_uids.count(); i++ ) { 412 for (uint i = 0; i < m_uids.count(); i++ ) {
410 qu += " UID = " + QString::number( m_uids[i] ) + " OR"; 413 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
411 } 414 }
412 qu.remove( qu.length()-2, 2 ); // Hmmmm.. 415 qu.remove( qu.length()-2, 2 ); // Hmmmm..
413 return qu; 416 return qu;
414 } 417 }
415 */ 418 */
416#ifdef __STORE_HORIZONTAL_ 419#ifdef __STORE_HORIZONTAL_
417 QString FindQuery::single()const{ 420 QString FindQuery::single()const{
418 QString qu = "select *"; 421 QString qu = "select *";
419 qu += " from addressbook where uid = " + QString::number(m_uid); 422 qu += " from addressbook where uid = " + QString::number(m_uid);
420 423
421 // qWarning("find query: %s", qu.latin1() ); 424 // qWarning("find query: %s", qu.latin1() );
422 return qu; 425 return qu;
423 } 426 }
424#else 427#else
425 QString FindQuery::single()const{ 428 QString FindQuery::single()const{
426 QString qu = "select uid, type, value from addressbook where uid = "; 429 QString qu = "select uid, type, value from addressbook where uid = ";
427 qu += QString::number(m_uid); 430 qu += QString::number(m_uid);
428 return qu; 431 return qu;
429 } 432 }
430#endif 433#endif
431 434
432 435
433 FindCustomQuery::FindCustomQuery(int uid) 436 FindCustomQuery::FindCustomQuery(int uid)
434 : OSQLQuery(), m_uid( uid ) { 437 : OSQLQuery(), m_uid( uid ) {
435 } 438 }
436 FindCustomQuery::FindCustomQuery(const QArray<int>& ints) 439 FindCustomQuery::FindCustomQuery(const QArray<int>& ints)
437 : OSQLQuery(), m_uids( ints ){ 440 : OSQLQuery(), m_uids( ints ){
438 } 441 }
439 FindCustomQuery::~FindCustomQuery() { 442 FindCustomQuery::~FindCustomQuery() {
440 } 443 }
441 QString FindCustomQuery::query()const{ 444 QString FindCustomQuery::query()const{
442 // if ( m_uids.count() == 0 ) 445 // if ( m_uids.count() == 0 )
443 return single(); 446 return single();
444 } 447 }
445 QString FindCustomQuery::single()const{ 448 QString FindCustomQuery::single()const{
446 QString qu = "select uid, type, value from custom_data where uid = "; 449 QString qu = "select uid, type, value from custom_data where uid = ";
447 qu += QString::number(m_uid); 450 qu += QString::number(m_uid);
448 return qu; 451 return qu;
449 } 452 }
450 453
451}; 454};
452 455
453 456
454/* --------------------------------------------------------------------------- */ 457/* --------------------------------------------------------------------------- */
455 458
456OContactAccessBackend_SQL::OContactAccessBackend_SQL ( const QString& /* appname */, 459OContactAccessBackend_SQL::OContactAccessBackend_SQL ( const QString& /* appname */,
457 const QString& filename ): m_changed(false) 460 const QString& filename ):
461 OContactAccessBackend(), m_changed(false), m_driver( NULL )
458{ 462{
459 qWarning("C'tor OContactAccessBackend_SQL starts"); 463 qWarning("C'tor OContactAccessBackend_SQL starts");
460 QTime t; 464 QTime t;
461 t.start(); 465 t.start();
462 466
463 /* Expecting to access the default filename if nothing else is set */ 467 /* Expecting to access the default filename if nothing else is set */
464 if ( filename.isEmpty() ){ 468 if ( filename.isEmpty() ){
465 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" ); 469 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" );
466 } else 470 } else
467 m_fileName = filename; 471 m_fileName = filename;
468 472
469 // Get the standart sql-driver from the OSQLManager.. 473 // Get the standart sql-driver from the OSQLManager..
470 OSQLManager man; 474 OSQLManager man;
471 m_driver = man.standard(); 475 m_driver = man.standard();
472 m_driver->setUrl( m_fileName ); 476 m_driver->setUrl( m_fileName );
473 477
474 load(); 478 load();
475 479
476 qWarning("C'tor OContactAccessBackend_SQL ends: %d ms", t.elapsed() ); 480 qWarning("C'tor OContactAccessBackend_SQL ends: %d ms", t.elapsed() );
477} 481}
478 482
483OContactAccessBackend_SQL::~OContactAccessBackend_SQL ()
484{
485 if( m_driver )
486 delete m_driver;
487}
479 488
480bool OContactAccessBackend_SQL::load () 489bool OContactAccessBackend_SQL::load ()
481{ 490{
482 if (!m_driver->open() ) 491 if (!m_driver->open() )
483 return false; 492 return false;
484 493
485 // Don't expect that the database exists. 494 // Don't expect that the database exists.
486 // It is save here to create the table, even if it 495 // It is save here to create the table, even if it
487 // do exist. ( Is that correct for all databases ?? ) 496 // do exist. ( Is that correct for all databases ?? )
488 CreateQuery creat; 497 CreateQuery creat;
489 OSQLResult res = m_driver->query( &creat ); 498 OSQLResult res = m_driver->query( &creat );
490 499
491 update(); 500 update();
492 501
493 return true; 502 return true;
494 503
495} 504}
496 505
497bool OContactAccessBackend_SQL::reload() 506bool OContactAccessBackend_SQL::reload()
498{ 507{
499 return load(); 508 return load();
500} 509}
501 510
502bool OContactAccessBackend_SQL::save() 511bool OContactAccessBackend_SQL::save()
503{ 512{
504 return m_driver->close(); 513 return m_driver->close();
505} 514}
506 515
507 516
508void OContactAccessBackend_SQL::clear () 517void OContactAccessBackend_SQL::clear ()
509{ 518{
510 ClearQuery cle; 519 ClearQuery cle;
511 OSQLResult res = m_driver->query( &cle ); 520 OSQLResult res = m_driver->query( &cle );
512 CreateQuery qu; 521 CreateQuery qu;
513 res = m_driver->query(&qu); 522 res = m_driver->query(&qu);
514} 523}
515 524
516bool OContactAccessBackend_SQL::wasChangedExternally() 525bool OContactAccessBackend_SQL::wasChangedExternally()
517{ 526{
518 return false; 527 return false;
519} 528}
520 529
521QArray<int> OContactAccessBackend_SQL::allRecords() const 530QArray<int> OContactAccessBackend_SQL::allRecords() const
522{ 531{
523 532
524 // FIXME: Think about cute handling of changed tables.. 533 // FIXME: Think about cute handling of changed tables..
525 // Thus, we don't have to call update here... 534 // Thus, we don't have to call update here...
526 if ( m_changed ) 535 if ( m_changed )
527 ((OContactAccessBackend_SQL*)this)->update(); 536 ((OContactAccessBackend_SQL*)this)->update();
528 537
529 return m_uids; 538 return m_uids;
530} 539}
531 540
532bool OContactAccessBackend_SQL::add ( const OContact &newcontact ) 541bool OContactAccessBackend_SQL::add ( const OContact &newcontact )
533{ 542{
534 InsertQuery ins( newcontact ); 543 InsertQuery ins( newcontact );
535 OSQLResult res = m_driver->query( &ins ); 544 OSQLResult res = m_driver->query( &ins );
536 545
537 if ( res.state() == OSQLResult::Failure ) 546 if ( res.state() == OSQLResult::Failure )
538 return false; 547 return false;
539 548
540 int c = m_uids.count(); 549 int c = m_uids.count();
541 m_uids.resize( c+1 ); 550 m_uids.resize( c+1 );
542 m_uids[c] = newcontact.uid(); 551 m_uids[c] = newcontact.uid();
543 552
544 return true; 553 return true;
545} 554}
546 555
547 556
548bool OContactAccessBackend_SQL::remove ( int uid ) 557bool OContactAccessBackend_SQL::remove ( int uid )
549{ 558{
550 RemoveQuery rem( uid ); 559 RemoveQuery rem( uid );
551 OSQLResult res = m_driver->query(&rem ); 560 OSQLResult res = m_driver->query(&rem );
552 561
553 if ( res.state() == OSQLResult::Failure ) 562 if ( res.state() == OSQLResult::Failure )
554 return false; 563 return false;
555 564
556 m_changed = true; 565 m_changed = true;
557 566
558 return true; 567 return true;
559} 568}
560 569
561bool OContactAccessBackend_SQL::replace ( const OContact &contact ) 570bool OContactAccessBackend_SQL::replace ( const OContact &contact )
562{ 571{
563 if ( !remove( contact.uid() ) ) 572 if ( !remove( contact.uid() ) )
564 return false; 573 return false;
565 574
566 return add( contact ); 575 return add( contact );
567} 576}
568 577
569 578
570OContact OContactAccessBackend_SQL::find ( int uid ) const 579OContact OContactAccessBackend_SQL::find ( int uid ) const
571{ 580{
572 qWarning("OContactAccessBackend_SQL::find()"); 581 qWarning("OContactAccessBackend_SQL::find()");
573 QTime t; 582 QTime t;
574 t.start(); 583 t.start();
575 584
576 OContact retContact( requestNonCustom( uid ) ); 585 OContact retContact( requestNonCustom( uid ) );
577 retContact.setExtraMap( requestCustom( uid ) ); 586 retContact.setExtraMap( requestCustom( uid ) );
578 587
579 qWarning("OContactAccessBackend_SQL::find() needed: %d ms", t.elapsed() ); 588 qWarning("OContactAccessBackend_SQL::find() needed: %d ms", t.elapsed() );
580 return retContact; 589 return retContact;
581} 590}
582 591
583 592
584 593
585QArray<int> OContactAccessBackend_SQL::queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() ) 594QArray<int> OContactAccessBackend_SQL::queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() )
586{ 595{
587 QString qu = "SELECT uid FROM addressbook WHERE"; 596 QString qu = "SELECT uid FROM addressbook WHERE";
588 597
589 QMap<int, QString> queryFields = query.toMap(); 598 QMap<int, QString> queryFields = query.toMap();
590 QStringList fieldList = OContactFields::untrfields( false ); 599 QStringList fieldList = OContactFields::untrfields( false );
591 QMap<QString, int> translate = OContactFields::untrFieldsToId(); 600 QMap<QString, int> translate = OContactFields::untrFieldsToId();
592 601
593 // Convert every filled field to a SQL-Query 602 // Convert every filled field to a SQL-Query
594 bool isAnyFieldSelected = false; 603 bool isAnyFieldSelected = false;
595 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 604 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
596 int id = translate[*it]; 605 int id = translate[*it];
597 QString queryStr = queryFields[id]; 606 QString queryStr = queryFields[id];
598 if ( !queryStr.isEmpty() ){ 607 if ( !queryStr.isEmpty() ){
599 isAnyFieldSelected = true; 608 isAnyFieldSelected = true;
600 switch( id ){ 609 switch( id ){
601 default: 610 default:
602 // Switching between case sensitive and insensitive... 611 // Switching between case sensitive and insensitive...
603 // LIKE is not case sensitive, GLOB is case sensitive 612 // LIKE is not case sensitive, GLOB is case sensitive
604 // Do exist a better solution to switch this ? 613 // Do exist a better solution to switch this ?
605 if ( settings & OContactAccess::IgnoreCase ) 614 if ( settings & OContactAccess::IgnoreCase )
606 qu += "(\"" + *it + "\"" + " LIKE " + "'" 615 qu += "(\"" + *it + "\"" + " LIKE " + "'"
607 + queryStr.replace(QRegExp("\\*"),"%") + "'" + ") AND "; 616 + queryStr.replace(QRegExp("\\*"),"%") + "'" + ") AND ";
608 else 617 else
609 qu += "(\"" + *it + "\"" + " GLOB " + "'" 618 qu += "(\"" + *it + "\"" + " GLOB " + "'"
610 + queryStr + "'" + ") AND "; 619 + queryStr + "'" + ") AND ";
611 620
612 } 621 }
613 } 622 }
614 } 623 }
615 // Skip trailing "AND" 624 // Skip trailing "AND"
616 if ( isAnyFieldSelected ) 625 if ( isAnyFieldSelected )
617 qu = qu.left( qu.length() - 4 ); 626 qu = qu.left( qu.length() - 4 );
618 627
619 qWarning( "queryByExample query: %s", qu.latin1() ); 628 qWarning( "queryByExample query: %s", qu.latin1() );
620 629
621 // Execute query and return the received uid's 630 // Execute query and return the received uid's
622 OSQLRawQuery raw( qu ); 631 OSQLRawQuery raw( qu );
623 OSQLResult res = m_driver->query( &raw ); 632 OSQLResult res = m_driver->query( &raw );
624 if ( res.state() != OSQLResult::Success ){ 633 if ( res.state() != OSQLResult::Success ){
625 QArray<int> empty; 634 QArray<int> empty;
626 return empty; 635 return empty;
627 } 636 }
628 637
629 QArray<int> list = extractUids( res ); 638 QArray<int> list = extractUids( res );
630 639
631 return list; 640 return list;
632} 641}
633 642
634QArray<int> OContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const 643QArray<int> OContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
635{ 644{
636 QArray<int> nix(0); 645 QArray<int> nix(0);
637 return nix; 646 return nix;
638} 647}
639 648
640const uint OContactAccessBackend_SQL::querySettings() 649const uint OContactAccessBackend_SQL::querySettings()
641{ 650{
642 return OContactAccess::IgnoreCase 651 return OContactAccess::IgnoreCase
643 || OContactAccess::WildCards; 652 || OContactAccess::WildCards;
644} 653}
645 654
646bool OContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const 655bool OContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const
647{ 656{
648 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay 657 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
649 * may be added with any of the other settings. IgnoreCase should never used alone. 658 * may be added with any of the other settings. IgnoreCase should never used alone.
650 * Wildcards, RegExp, ExactMatch should never used at the same time... 659 * Wildcards, RegExp, ExactMatch should never used at the same time...
651 */ 660 */
652 661
653 // Step 1: Check whether the given settings are supported by this backend 662 // Step 1: Check whether the given settings are supported by this backend
654 if ( ( querySettings & ( 663 if ( ( querySettings & (
655 OContactAccess::IgnoreCase 664 OContactAccess::IgnoreCase
656 | OContactAccess::WildCards 665 | OContactAccess::WildCards
657 // | OContactAccess::DateDiff 666 // | OContactAccess::DateDiff
658 // | OContactAccess::DateYear 667 // | OContactAccess::DateYear
659 // | OContactAccess::DateMonth 668 // | OContactAccess::DateMonth
660 // | OContactAccess::DateDay 669 // | OContactAccess::DateDay
661 // | OContactAccess::RegExp 670 // | OContactAccess::RegExp
662 // | OContactAccess::ExactMatch 671 // | OContactAccess::ExactMatch
663 ) ) != querySettings ) 672 ) ) != querySettings )
664 return false; 673 return false;
665 674
666 // Step 2: Check whether the given combinations are ok.. 675 // Step 2: Check whether the given combinations are ok..
667 676
668 // IngoreCase alone is invalid 677 // IngoreCase alone is invalid
669 if ( querySettings == OContactAccess::IgnoreCase ) 678 if ( querySettings == OContactAccess::IgnoreCase )
670 return false; 679 return false;
671 680
672 // WildCards, RegExp and ExactMatch should never used at the same time 681 // WildCards, RegExp and ExactMatch should never used at the same time
673 switch ( querySettings & ~( OContactAccess::IgnoreCase 682 switch ( querySettings & ~( OContactAccess::IgnoreCase
674 | OContactAccess::DateDiff 683 | OContactAccess::DateDiff
675 | OContactAccess::DateYear 684 | OContactAccess::DateYear
676 | OContactAccess::DateMonth 685 | OContactAccess::DateMonth
677 | OContactAccess::DateDay 686 | OContactAccess::DateDay
678 ) 687 )
679 ){ 688 ){
680 case OContactAccess::RegExp: 689 case OContactAccess::RegExp:
681 return ( true ); 690 return ( true );
682 case OContactAccess::WildCards: 691 case OContactAccess::WildCards:
683 return ( true ); 692 return ( true );
684 case OContactAccess::ExactMatch: 693 case OContactAccess::ExactMatch:
685 return ( true ); 694 return ( true );
686 case 0: // one of the upper removed bits were set.. 695 case 0: // one of the upper removed bits were set..
687 return ( true ); 696 return ( true );
688 default: 697 default:
689 return ( false ); 698 return ( false );
690 } 699 }
691 700
692} 701}
693 702
694QArray<int> OContactAccessBackend_SQL::sorted( bool asc, int , int , int ) 703QArray<int> OContactAccessBackend_SQL::sorted( bool asc, int , int , int )
695{ 704{
696 QTime t; 705 QTime t;
697 t.start(); 706 t.start();
698 707
699#ifdef __STORE_HORIZONTAL_ 708#ifdef __STORE_HORIZONTAL_
700 QString query = "SELECT uid FROM addressbook "; 709 QString query = "SELECT uid FROM addressbook ";
701 query += "ORDER BY \"Last Name\" "; 710 query += "ORDER BY \"Last Name\" ";
702#else 711#else
703 QString query = "SELECT uid FROM addressbook WHERE type = 'Last Name' "; 712 QString query = "SELECT uid FROM addressbook WHERE type = 'Last Name' ";
704 query += "ORDER BY upper( value )"; 713 query += "ORDER BY upper( value )";
705#endif 714#endif
706 715
707 if ( !asc ) 716 if ( !asc )
708 query += "DESC"; 717 query += "DESC";
709 718
710 // qWarning("sorted query is: %s", query.latin1() ); 719 // qWarning("sorted query is: %s", query.latin1() );
711 720
712 OSQLRawQuery raw( query ); 721 OSQLRawQuery raw( query );
713 OSQLResult res = m_driver->query( &raw ); 722 OSQLResult res = m_driver->query( &raw );
714 if ( res.state() != OSQLResult::Success ){ 723 if ( res.state() != OSQLResult::Success ){
715 QArray<int> empty; 724 QArray<int> empty;
716 return empty; 725 return empty;
717 } 726 }
718 727
719 QArray<int> list = extractUids( res ); 728 QArray<int> list = extractUids( res );
720 729
721 qWarning("sorted needed %d ms!", t.elapsed() ); 730 qWarning("sorted needed %d ms!", t.elapsed() );
722 return list; 731 return list;
723} 732}
724 733
725 734
726void OContactAccessBackend_SQL::update() 735void OContactAccessBackend_SQL::update()
727{ 736{
728 qWarning("Update starts"); 737 qWarning("Update starts");
729 QTime t; 738 QTime t;
730 t.start(); 739 t.start();
731 740
732 // Now load the database set and extract the uid's 741 // Now load the database set and extract the uid's
733 // which will be held locally 742 // which will be held locally
734 743
diff --git a/libopie/pim/ocontactaccessbackend_sql.h b/libopie/pim/ocontactaccessbackend_sql.h
index bb22551..b8f1d8d 100644
--- a/libopie/pim/ocontactaccessbackend_sql.h
+++ b/libopie/pim/ocontactaccessbackend_sql.h
@@ -1,96 +1,101 @@
1/* 1/*
2 * SQL Backend for the OPIE-Contact Database. 2 * SQL Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * 5 *
6 * ===================================================================== 6 * =====================================================================
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * ===================================================================== 11 * =====================================================================
12 * 12 *
13 * 13 *
14 * ===================================================================== 14 * =====================================================================
15 * Version: $Id$ 15 * Version: $Id$
16 * ===================================================================== 16 * =====================================================================
17 * History: 17 * History:
18 * $Log$ 18 * $Log$
19 * Revision 1.2 2003/12/08 15:18:11 eilers
20 * Committing unfinished sql implementation before merging to libopie2 starts..
21 *
19 * Revision 1.1 2003/09/22 14:31:16 eilers 22 * Revision 1.1 2003/09/22 14:31:16 eilers
20 * Added first experimental incarnation of sql-backend for addressbook. 23 * Added first experimental incarnation of sql-backend for addressbook.
21 * Some modifications to be able to compile the todo sql-backend. 24 * Some modifications to be able to compile the todo sql-backend.
22 * A lot of changes fill follow... 25 * A lot of changes fill follow...
23 * 26 *
24 * 27 *
25 */ 28 */
26 29
27#ifndef _OContactAccessBackend_SQL_ 30#ifndef _OContactAccessBackend_SQL_
28#define _OContactAccessBackend_SQL_ 31#define _OContactAccessBackend_SQL_
29 32
30#include "ocontactaccessbackend.h" 33#include "ocontactaccessbackend.h"
31#include "ocontactaccess.h" 34#include "ocontactaccess.h"
32 35
33#include <qlist.h> 36#include <qlist.h>
34#include <qdict.h> 37#include <qdict.h>
35 38
36class OSQLDriver; 39class OSQLDriver;
37class OSQLResult; 40class OSQLResult;
38class OSQLResultItem; 41class OSQLResultItem;
39 42
40/* the default xml implementation */ 43/* the default xml implementation */
41/** 44/**
42 * This class is the SQL implementation of a Contact backend 45 * This class is the SQL implementation of a Contact backend
43 * it does implement everything available for OContact. 46 * it does implement everything available for OContact.
44 * @see OPimAccessBackend for more information of available methods 47 * @see OPimAccessBackend for more information of available methods
45 */ 48 */
46class OContactAccessBackend_SQL : public OContactAccessBackend { 49class OContactAccessBackend_SQL : public OContactAccessBackend {
47 public: 50 public:
48 OContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null ); 51 OContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null );
49 52
53 ~OContactAccessBackend_SQL ();
54
50 bool save(); 55 bool save();
51 56
52 bool load (); 57 bool load ();
53 58
54 void clear (); 59 void clear ();
55 60
56 bool wasChangedExternally(); 61 bool wasChangedExternally();
57 62
58 QArray<int> allRecords() const; 63 QArray<int> allRecords() const;
59 64
60 OContact find ( int uid ) const; 65 OContact find ( int uid ) const;
61 // FIXME: Add lookahead-cache support ! 66 // FIXME: Add lookahead-cache support !
62 //OContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const; 67 //OContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
63 68
64 QArray<int> queryByExample ( const OContact &query, int settings, 69 QArray<int> queryByExample ( const OContact &query, int settings,
65 const QDateTime& d ); 70 const QDateTime& d );
66 71
67 QArray<int> matchRegexp( const QRegExp &r ) const; 72 QArray<int> matchRegexp( const QRegExp &r ) const;
68 73
69 const uint querySettings(); 74 const uint querySettings();
70 75
71 bool hasQuerySettings (uint querySettings) const; 76 bool hasQuerySettings (uint querySettings) const;
72 77
73 // Currently only asc implemented.. 78 // Currently only asc implemented..
74 QArray<int> sorted( bool asc, int , int , int ); 79 QArray<int> sorted( bool asc, int , int , int );
75 bool add ( const OContact &newcontact ); 80 bool add ( const OContact &newcontact );
76 81
77 bool replace ( const OContact &contact ); 82 bool replace ( const OContact &contact );
78 83
79 bool remove ( int uid ); 84 bool remove ( int uid );
80 bool reload(); 85 bool reload();
81 86
82 private: 87 private:
83 QArray<int> extractUids( OSQLResult& res ) const; 88 QArray<int> extractUids( OSQLResult& res ) const;
84 QMap<int, QString> requestNonCustom( int uid ) const; 89 QMap<int, QString> requestNonCustom( int uid ) const;
85 QMap<QString, QString> requestCustom( int uid ) const; 90 QMap<QString, QString> requestCustom( int uid ) const;
86 void update(); 91 void update();
87 92
88 protected: 93 protected:
89 bool m_changed; 94 bool m_changed;
90 QString m_fileName; 95 QString m_fileName;
91 QArray<int> m_uids; 96 QArray<int> m_uids;
92 97
93 OSQLDriver* m_driver; 98 OSQLDriver* m_driver;
94}; 99};
95 100
96#endif 101#endif
diff --git a/libopie/pim/odatebookaccessbackend_sql.cpp b/libopie/pim/odatebookaccessbackend_sql.cpp
new file mode 100644
index 0000000..9769bf7
--- a/dev/null
+++ b/libopie/pim/odatebookaccessbackend_sql.cpp
@@ -0,0 +1,221 @@
1/*
2 * SQL Backend for the OPIE-Calender Database.
3 *
4 * Copyright (c) 2003 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * =====================================================================
13 * Version: $Id$
14 * =====================================================================
15 * History:
16 * $Log$
17 * Revision 1.1 2003/12/08 15:18:12 eilers
18 * Committing unfinished sql implementation before merging to libopie2 starts..
19 *
20 *
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25
26#include <qarray.h>
27#include <qstringlist.h>
28
29#include "orecur.h"
30#include "odatebookaccessbackend_sql.h"
31
32#include <opie2/osqldriver.h>
33#include <opie2/osqlresult.h>
34#include <opie2/osqlmanager.h>
35#include <opie2/osqlquery.h>
36
37namespace {
38
39
40
41};
42
43ODateBookAccessBackend_SQL::ODateBookAccessBackend_SQL( const QString& ,
44 const QString& fileName )
45 : ODateBookAccessBackend(), m_driver( NULL )
46{
47 m_fileName = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.db" ) : fileName;
48
49 // Get the standart sql-driver from the OSQLManager..
50 OSQLManager man;
51 m_driver = man.standard();
52 m_driver->setUrl( m_fileName );
53
54 initFields();
55
56 load();
57}
58
59ODateBookAccessBackend_SQL::~ODateBookAccessBackend_SQL() {
60}
61
62void ODateBookAccessBackend_SQL::initFields()
63{
64
65 // This map contains the translation of the fieldtype id's to
66 // the names of the table columns
67 m_fieldMap.insert( OEvent::FUid, "uid" );
68 m_fieldMap.insert( OEvent::FCategories, "Categories" );
69 m_fieldMap.insert( OEvent::FDescription, "Description" );
70 m_fieldMap.insert( OEvent::FLocation, "Location" );
71 m_fieldMap.insert( OEvent::FType, "Type" );
72 m_fieldMap.insert( OEvent::FAlarm, "Alarm" );
73 m_fieldMap.insert( OEvent::FSound, "Sound" );
74 m_fieldMap.insert( OEvent::FRType, "RType" );
75 m_fieldMap.insert( OEvent::FRWeekdays, "RWeekdays" );
76 m_fieldMap.insert( OEvent::FRPosition, "RPosition" );
77 m_fieldMap.insert( OEvent::FRFreq, "RFreq" );
78 m_fieldMap.insert( OEvent::FRHasEndDate, "RHasEndDate" );
79 m_fieldMap.insert( OEvent::FREndDate, "REndDate" );
80 m_fieldMap.insert( OEvent::FRCreated, "RCreated" );
81 m_fieldMap.insert( OEvent::FRExeptions, "RExceptions" );
82 m_fieldMap.insert( OEvent::FStart, "Start" );
83 m_fieldMap.insert( OEvent::FEnd, "End" );
84 m_fieldMap.insert( OEvent::FNote, "Note" );
85 m_fieldMap.insert( OEvent::FTimeZone, "TimeZone" );
86 m_fieldMap.insert( OEvent::FRecParent, "RecParent" );
87 m_fieldMap.insert( OEvent::FRecChildren, "Recchildren" );
88}
89
90bool ODateBookAccessBackend_SQL::load()
91{
92 if (!m_driver->open() )
93 return false;
94
95 // Don't expect that the database exists.
96 // It is save here to create the table, even if it
97 // do exist. ( Is that correct for all databases ?? )
98 QStringqu = "create table datebook( uid INTEGER PRIMARY KEY ";
99
100 QMap<int, QString>::Iterator it;
101 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
102 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( it.data() );
103 }
104 qu += " );";
105
106 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
107
108 OSQLRawQuery raw( qu );
109 OSQLResult res = m_driver->query( &raw );
110 if ( res.state() != OSQLResult::Success )
111 return false;
112
113 update();
114
115 return true;
116}
117
118void ODateBookAccessBackend_SQL::update()
119{
120
121 QString qu = "select uid from datebook";
122 OSQLRawQuery raw( qu );
123 OSQLResult res = m_driver->query( &raw );
124 if ( res.state() != OSQLResult::Success ){
125 m_uids.clear();
126 return;
127 }
128
129 m_uids = extractUids( res );
130
131}
132
133QArray<int> ODateBookAccessBackend_SQL::extractUids( OSQLResult& res ) const
134{
135 qWarning("extractUids");
136
137 OSQLResultItem::ValueList list = res.results();
138 OSQLResultItem::ValueList::Iterator it;
139 QArray<int> ints(list.count() );
140 qWarning(" count = %d", list.count() );
141
142 int i = 0;
143 for (it = list.begin(); it != list.end(); ++it ) {
144 ints[i] = (*it).data("uid").toInt();
145 i++;
146 }
147
148 return ints;
149
150}
151
152bool ODateBookAccessBackend_SQL::reload()
153{
154 return load();
155}
156
157bool ODateBookAccessBackend_SQL::save()
158{
159 return m_driver->close();
160}
161
162QArray<int> ODateBookAccessBackend_SQL::allRecords()const
163{
164 return m_uids;
165}
166
167QArray<int> ODateBookAccessBackend_SQL::queryByExample(const OEvent&, int, const QDateTime& ) {
168 return QArray<int>();
169}
170
171void ODateBookAccessBackend_SQL::clear()
172{
173 QString qu = "drop table datebook;";
174 qu += "drop table custom_data;";
175
176 OSQLRawQuery raw( qu );
177 OSQLResult res = m_driver->query( &raw );
178
179}
180
181
182OEvent ODateBookAccessBackend_SQL::find( int uid ) const{
183}
184
185bool ODateBookAccessBackend_SQL::add( const OEvent& ev ) {
186 return true;
187}
188bool ODateBookAccessBackend_SQL::remove( int uid ) {
189
190 return true;
191}
192bool ODateBookAccessBackend_SQL::replace( const OEvent& ev ) {
193 remove( ev.uid() );
194 return add( ev );
195}
196QArray<int> ODateBookAccessBackend_SQL::rawEvents()const {
197 return allRecords();
198}
199QArray<int> ODateBookAccessBackend_SQL::rawRepeats()const {
200
201 return ints;
202}
203QArray<int> ODateBookAccessBackend_SQL::nonRepeats()const {
204
205 return ints;
206}
207OEvent::ValueList ODateBookAccessBackend_SQL::directNonRepeats() {
208
209 return list;
210}
211OEvent::ValueList ODateBookAccessBackend_SQL::directRawRepeats() {
212
213 return list;
214}
215
216
217QArray<int> ODateBookAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
218{
219
220 return m_currentQuery;
221}
diff --git a/libopie/pim/odatebookaccessbackend_sql.h b/libopie/pim/odatebookaccessbackend_sql.h
new file mode 100644
index 0000000..85e0d4f
--- a/dev/null
+++ b/libopie/pim/odatebookaccessbackend_sql.h
@@ -0,0 +1,60 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
2#define OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
3
4#include <qmap.h>
5
6#include "odatebookaccessbackend.h"
7
8class OSQLDriver;
9
10/**
11 * This is the default SQL implementation for DateBoook SQL storage
12 * It fully implements the interface
13 * @see ODateBookAccessBackend
14 * @see OPimAccessBackend
15 */
16class ODateBookAccessBackend_SQL : public ODateBookAccessBackend {
17public:
18 ODateBookAccessBackend_SQL( const QString& appName,
19 const QString& fileName = QString::null);
20 ~ODateBookAccessBackend_SQL();
21
22 bool load();
23 bool reload();
24 bool save();
25
26 QArray<int> allRecords()const;
27 QArray<int> matchRegexp(const QRegExp &r) const;
28 QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
29 OEvent find( int uid )const;
30 void clear();
31 bool add( const OEvent& ev );
32 bool remove( int uid );
33 bool replace( const OEvent& ev );
34
35 QArray<UID> rawEvents()const;
36 QArray<UID> rawRepeats()const;
37 QArray<UID> nonRepeats()const;
38
39 OEvent::ValueList directNonRepeats();
40 OEvent::ValueList directRawRepeats();
41
42private:
43 bool loadFile();
44 QString m_fileName;
45 QArray<int> m_uids;
46
47 QMap<int, QString> m_fieldMap;
48
49 OSQLDriver* m_driver;
50
51 class Private;
52 Private *d;
53
54 void initFields();
55 void update();
56 QArray<int> extractUids( OSQLResult& res ) const;
57
58};
59
60#endif
diff --git a/libopie/pim/odatebookaccessbackend_xml.cpp b/libopie/pim/odatebookaccessbackend_xml.cpp
index 39c43c5..929d004 100644
--- a/libopie/pim/odatebookaccessbackend_xml.cpp
+++ b/libopie/pim/odatebookaccessbackend_xml.cpp
@@ -1,606 +1,612 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <stdio.h> 4#include <stdio.h>
5#include <stdlib.h> 5#include <stdlib.h>
6 6
7#include <sys/types.h> 7#include <sys/types.h>
8#include <sys/mman.h> 8#include <sys/mman.h>
9#include <sys/stat.h> 9#include <sys/stat.h>
10 10
11#include <unistd.h> 11#include <unistd.h>
12 12
13#include <qasciidict.h> 13#include <qasciidict.h>
14#include <qfile.h> 14#include <qfile.h>
15 15
16#include <qtopia/global.h> 16#include <qtopia/global.h>
17#include <qtopia/stringutil.h> 17#include <qtopia/stringutil.h>
18#include <qtopia/timeconversion.h> 18#include <qtopia/timeconversion.h>
19 19
20#include "opimnotifymanager.h" 20#include "opimnotifymanager.h"
21#include "orecur.h" 21#include "orecur.h"
22#include "otimezone.h" 22#include "otimezone.h"
23#include "odatebookaccessbackend_xml.h" 23#include "odatebookaccessbackend_xml.h"
24 24
25namespace { 25namespace {
26 // FROM TT again 26 // FROM TT again
27char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen) 27char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
28{ 28{
29 char needleChar; 29 char needleChar;
30 char haystackChar; 30 char haystackChar;
31 if (!needle || !haystack || !hLen || !nLen) 31 if (!needle || !haystack || !hLen || !nLen)
32 return 0; 32 return 0;
33 33
34 const char* hsearch = haystack; 34 const char* hsearch = haystack;
35 35
36 if ((needleChar = *needle++) != 0) { 36 if ((needleChar = *needle++) != 0) {
37 nLen--; //(to make up for needle++) 37 nLen--; //(to make up for needle++)
38 do { 38 do {
39 do { 39 do {
40 if ((haystackChar = *hsearch++) == 0) 40 if ((haystackChar = *hsearch++) == 0)
41 return (0); 41 return (0);
42 if (hsearch >= haystack + hLen) 42 if (hsearch >= haystack + hLen)
43 return (0); 43 return (0);
44 } while (haystackChar != needleChar); 44 } while (haystackChar != needleChar);
45 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0); 45 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
46 hsearch--; 46 hsearch--;
47 } 47 }
48 return ((char *)hsearch); 48 return ((char *)hsearch);
49} 49}
50} 50}
51 51
52namespace { 52namespace {
53 time_t start, end, created, rp_end; 53 time_t start, end, created, rp_end;
54 ORecur* rec; 54 ORecur* rec;
55 ORecur* recur() { 55 ORecur* recur() {
56 if (!rec) 56 if (!rec)
57 rec = new ORecur; 57 rec = new ORecur;
58 58
59 return rec; 59 return rec;
60 } 60 }
61 int alarmTime; 61 int alarmTime;
62 int snd; 62 int snd;
63 enum Attribute{ 63 enum Attribute{
64 FDescription = 0, 64 FDescription = 0,
65 FLocation, 65 FLocation,
66 FCategories, 66 FCategories,
67 FUid, 67 FUid,
68 FType, 68 FType,
69 FAlarm, 69 FAlarm,
70 FSound, 70 FSound,
71 FRType, 71 FRType,
72 FRWeekdays, 72 FRWeekdays,
73 FRPosition, 73 FRPosition,
74 FRFreq, 74 FRFreq,
75 FRHasEndDate, 75 FRHasEndDate,
76 FREndDate, 76 FREndDate,
77 FRStart, 77 FRStart,
78 FREnd, 78 FREnd,
79 FNote, 79 FNote,
80 FCreated, 80 FCreated, // Should't this be called FRCreated ?
81 FTimeZone, 81 FTimeZone,
82 FRecParent, 82 FRecParent,
83 FRecChildren, 83 FRecChildren,
84 FExceptions 84 FExceptions
85 }; 85 };
86
87 // FIXME: Use OEvent::toMap() here !! (eilers)
86 inline void save( const OEvent& ev, QString& buf ) { 88 inline void save( const OEvent& ev, QString& buf ) {
87 qWarning("Saving %d %s", ev.uid(), ev.description().latin1() ); 89 qWarning("Saving %d %s", ev.uid(), ev.description().latin1() );
88 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\""; 90 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
89 if (!ev.location().isEmpty() ) 91 if (!ev.location().isEmpty() )
90 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\""; 92 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
91 93
92 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\""; 94 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
93 buf += " uid=\"" + QString::number( ev.uid() ) + "\""; 95 buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
94 96
95 if (ev.isAllDay() ) 97 if (ev.isAllDay() )
96 buf += " type=\"AllDay\""; // is that all ?? (eilers) 98 buf += " type=\"AllDay\""; // is that all ?? (eilers)
97 99
98 if (ev.hasNotifiers() ) { 100 if (ev.hasNotifiers() ) {
99 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first 101 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
100 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60; 102 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
101 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\""; 103 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
102 if ( alarm.sound() == OPimAlarm::Loud ) 104 if ( alarm.sound() == OPimAlarm::Loud )
103 buf += "loud"; 105 buf += "loud";
104 else 106 else
105 buf += "silent"; 107 buf += "silent";
106 buf += "\""; 108 buf += "\"";
107 } 109 }
108 if ( ev.hasRecurrence() ) { 110 if ( ev.hasRecurrence() ) {
109 buf += ev.recurrence().toString(); 111 buf += ev.recurrence().toString();
110 } 112 }
111 113
112 /* 114 /*
113 * fscking timezones :) well, we'll first convert 115 * fscking timezones :) well, we'll first convert
114 * the QDateTime to a QDateTime in UTC time 116 * the QDateTime to a QDateTime in UTC time
115 * and then we'll create a nice time_t 117 * and then we'll create a nice time_t
116 */ 118 */
117 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); 119 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
118 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\""; 120 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\"";
119 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\""; 121 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\"";
120 if (!ev.note().isEmpty() ) { 122 if (!ev.note().isEmpty() ) {
121 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\""; 123 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\"";
122 } 124 }
123 125
124 buf += " timezone=\""; 126 buf += " timezone=\"";
125 if ( ev.timeZone().isEmpty() ) 127 if ( ev.timeZone().isEmpty() )
126 buf += "None"; 128 buf += "None";
127 else 129 else
128 buf += ev.timeZone(); 130 buf += ev.timeZone();
129 buf += "\""; 131 buf += "\"";
130 132
131 if (ev.parent() != 0 ) { 133 if (ev.parent() != 0 ) {
132 buf += " recparent=\""+QString::number(ev.parent() )+"\""; 134 buf += " recparent=\""+QString::number(ev.parent() )+"\"";
133 } 135 }
134 136
135 if (ev.children().count() != 0 ) { 137 if (ev.children().count() != 0 ) {
136 QArray<int> children = ev.children(); 138 QArray<int> children = ev.children();
137 buf += " recchildren=\""; 139 buf += " recchildren=\"";
138 for ( uint i = 0; i < children.count(); i++ ) { 140 for ( uint i = 0; i < children.count(); i++ ) {
139 if ( i != 0 ) buf += " "; 141 if ( i != 0 ) buf += " ";
140 buf += QString::number( children[i] ); 142 buf += QString::number( children[i] );
141 } 143 }
142 buf+= "\""; 144 buf+= "\"";
143 } 145 }
144 146
145 // skip custom writing 147 // skip custom writing
146 } 148 }
147 149
148 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) { 150 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) {
149 QMap<int, OEvent>::ConstIterator it; 151 QMap<int, OEvent>::ConstIterator it;
150 QString buf; 152 QString buf;
151 QCString str; 153 QCString str;
152 int total_written; 154 int total_written;
153 for ( it = list.begin(); it != list.end(); ++it ) { 155 for ( it = list.begin(); it != list.end(); ++it ) {
154 buf = "<event"; 156 buf = "<event";
155 save( it.data(), buf ); 157 save( it.data(), buf );
156 buf += " />\n"; 158 buf += " />\n";
157 str = buf.utf8(); 159 str = buf.utf8();
158 160
159 total_written = file.writeBlock(str.data(), str.length() ); 161 total_written = file.writeBlock(str.data(), str.length() );
160 if ( total_written != int(str.length() ) ) 162 if ( total_written != int(str.length() ) )
161 return false; 163 return false;
162 } 164 }
163 return true; 165 return true;
164 } 166 }
165} 167}
166 168
167ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& , 169ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& ,
168 const QString& fileName ) 170 const QString& fileName )
169 : ODateBookAccessBackend() { 171 : ODateBookAccessBackend() {
170 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName; 172 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName;
171 m_changed = false; 173 m_changed = false;
172} 174}
173ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() { 175ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() {
174} 176}
175bool ODateBookAccessBackend_XML::load() { 177bool ODateBookAccessBackend_XML::load() {
176 return loadFile(); 178 return loadFile();
177} 179}
178bool ODateBookAccessBackend_XML::reload() { 180bool ODateBookAccessBackend_XML::reload() {
179 clear(); 181 clear();
180 return load(); 182 return load();
181} 183}
182bool ODateBookAccessBackend_XML::save() { 184bool ODateBookAccessBackend_XML::save() {
183 if (!m_changed) return true; 185 if (!m_changed) return true;
184 186
185 int total_written; 187 int total_written;
186 QString strFileNew = m_name + ".new"; 188 QString strFileNew = m_name + ".new";
187 189
188 QFile f( strFileNew ); 190 QFile f( strFileNew );
189 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false; 191 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false;
190 192
191 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); 193 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
192 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n"; 194 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
193 buf += "<events>\n"; 195 buf += "<events>\n";
194 QCString str = buf.utf8(); 196 QCString str = buf.utf8();
195 total_written = f.writeBlock( str.data(), str.length() ); 197 total_written = f.writeBlock( str.data(), str.length() );
196 if ( total_written != int(str.length() ) ) { 198 if ( total_written != int(str.length() ) ) {
197 f.close(); 199 f.close();
198 QFile::remove( strFileNew ); 200 QFile::remove( strFileNew );
199 return false; 201 return false;
200 } 202 }
201 203
202 if (!forAll( m_raw, f ) ) { 204 if (!forAll( m_raw, f ) ) {
203 f.close(); 205 f.close();
204 QFile::remove( strFileNew ); 206 QFile::remove( strFileNew );
205 return false; 207 return false;
206 } 208 }
207 if (!forAll( m_rep, f ) ) { 209 if (!forAll( m_rep, f ) ) {
208 f.close(); 210 f.close();
209 QFile::remove( strFileNew ); 211 QFile::remove( strFileNew );
210 return false; 212 return false;
211 } 213 }
212 214
213 buf = "</events>\n</DATEBOOK>\n"; 215 buf = "</events>\n</DATEBOOK>\n";
214 str = buf.utf8(); 216 str = buf.utf8();
215 total_written = f.writeBlock( str.data(), str.length() ); 217 total_written = f.writeBlock( str.data(), str.length() );
216 if ( total_written != int(str.length() ) ) { 218 if ( total_written != int(str.length() ) ) {
217 f.close(); 219 f.close();
218 QFile::remove( strFileNew ); 220 QFile::remove( strFileNew );
219 return false; 221 return false;
220 } 222 }
221 f.close(); 223 f.close();
222 224
223 if ( ::rename( strFileNew, m_name ) < 0 ) { 225 if ( ::rename( strFileNew, m_name ) < 0 ) {
224 QFile::remove( strFileNew ); 226 QFile::remove( strFileNew );
225 return false; 227 return false;
226 } 228 }
227 229
228 m_changed = false; 230 m_changed = false;
229 return true; 231 return true;
230} 232}
231QArray<int> ODateBookAccessBackend_XML::allRecords()const { 233QArray<int> ODateBookAccessBackend_XML::allRecords()const {
232 QArray<int> ints( m_raw.count()+ m_rep.count() ); 234 QArray<int> ints( m_raw.count()+ m_rep.count() );
233 uint i = 0; 235 uint i = 0;
234 QMap<int, OEvent>::ConstIterator it; 236 QMap<int, OEvent>::ConstIterator it;
235 237
236 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 238 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
237 ints[i] = it.key(); 239 ints[i] = it.key();
238 i++; 240 i++;
239 } 241 }
240 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 242 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
241 ints[i] = it.key(); 243 ints[i] = it.key();
242 i++; 244 i++;
243 } 245 }
244 246
245 return ints; 247 return ints;
246} 248}
247QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) { 249QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) {
248 return QArray<int>(); 250 return QArray<int>();
249} 251}
250void ODateBookAccessBackend_XML::clear() { 252void ODateBookAccessBackend_XML::clear() {
251 m_changed = true; 253 m_changed = true;
252 m_raw.clear(); 254 m_raw.clear();
253 m_rep.clear(); 255 m_rep.clear();
254} 256}
255OEvent ODateBookAccessBackend_XML::find( int uid ) const{ 257OEvent ODateBookAccessBackend_XML::find( int uid ) const{
256 if ( m_raw.contains( uid ) ) 258 if ( m_raw.contains( uid ) )
257 return m_raw[uid]; 259 return m_raw[uid];
258 else 260 else
259 return m_rep[uid]; 261 return m_rep[uid];
260} 262}
261bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { 263bool ODateBookAccessBackend_XML::add( const OEvent& ev ) {
262 m_changed = true; 264 m_changed = true;
263 if (ev.hasRecurrence() ) 265 if (ev.hasRecurrence() )
264 m_rep.insert( ev.uid(), ev ); 266 m_rep.insert( ev.uid(), ev );
265 else 267 else
266 m_raw.insert( ev.uid(), ev ); 268 m_raw.insert( ev.uid(), ev );
267 269
268 return true; 270 return true;
269} 271}
270bool ODateBookAccessBackend_XML::remove( int uid ) { 272bool ODateBookAccessBackend_XML::remove( int uid ) {
271 m_changed = true; 273 m_changed = true;
272 m_rep.remove( uid ); 274 m_rep.remove( uid );
273 m_rep.remove( uid ); 275 m_rep.remove( uid );
274 276
275 return true; 277 return true;
276} 278}
277bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { 279bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) {
278 replace( ev.uid() ); 280 replace( ev.uid() ); // ??? Shouldn't this be "remove( ev.uid() ) ??? (eilers)
279 return add( ev ); 281 return add( ev );
280} 282}
281QArray<int> ODateBookAccessBackend_XML::rawEvents()const { 283QArray<int> ODateBookAccessBackend_XML::rawEvents()const {
282 return allRecords(); 284 return allRecords();
283} 285}
284QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { 286QArray<int> ODateBookAccessBackend_XML::rawRepeats()const {
285 QArray<int> ints( m_rep.count() ); 287 QArray<int> ints( m_rep.count() );
286 uint i = 0; 288 uint i = 0;
287 QMap<int, OEvent>::ConstIterator it; 289 QMap<int, OEvent>::ConstIterator it;
288 290
289 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 291 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
290 ints[i] = it.key(); 292 ints[i] = it.key();
291 i++; 293 i++;
292 } 294 }
293 295
294 return ints; 296 return ints;
295} 297}
296QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { 298QArray<int> ODateBookAccessBackend_XML::nonRepeats()const {
297 QArray<int> ints( m_raw.count() ); 299 QArray<int> ints( m_raw.count() );
298 uint i = 0; 300 uint i = 0;
299 QMap<int, OEvent>::ConstIterator it; 301 QMap<int, OEvent>::ConstIterator it;
300 302
301 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 303 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
302 ints[i] = it.key(); 304 ints[i] = it.key();
303 i++; 305 i++;
304 } 306 }
305 307
306 return ints; 308 return ints;
307} 309}
308OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { 310OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() {
309 OEvent::ValueList list; 311 OEvent::ValueList list;
310 QMap<int, OEvent>::ConstIterator it; 312 QMap<int, OEvent>::ConstIterator it;
311 for (it = m_raw.begin(); it != m_raw.end(); ++it ) 313 for (it = m_raw.begin(); it != m_raw.end(); ++it )
312 list.append( it.data() ); 314 list.append( it.data() );
313 315
314 return list; 316 return list;
315} 317}
316OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { 318OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() {
317 OEvent::ValueList list; 319 OEvent::ValueList list;
318 QMap<int, OEvent>::ConstIterator it; 320 QMap<int, OEvent>::ConstIterator it;
319 for (it = m_rep.begin(); it != m_rep.end(); ++it ) 321 for (it = m_rep.begin(); it != m_rep.end(); ++it )
320 list.append( it.data() ); 322 list.append( it.data() );
321 323
322 return list; 324 return list;
323} 325}
326
327// FIXME: Use OEvent::fromMap() (eilers)
324bool ODateBookAccessBackend_XML::loadFile() { 328bool ODateBookAccessBackend_XML::loadFile() {
325 m_changed = false; 329 m_changed = false;
326 330
327 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); 331 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY );
328 if ( fd < 0 ) return false; 332 if ( fd < 0 ) return false;
329 333
330 struct stat attribute; 334 struct stat attribute;
331 if ( ::fstat(fd, &attribute ) == -1 ) { 335 if ( ::fstat(fd, &attribute ) == -1 ) {
332 ::close( fd ); 336 ::close( fd );
333 return false; 337 return false;
334 } 338 }
335 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 339 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 );
336 if ( map_addr == ( (caddr_t)-1) ) { 340 if ( map_addr == ( (caddr_t)-1) ) {
337 ::close( fd ); 341 ::close( fd );
338 return false; 342 return false;
339 } 343 }
340 344
341 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); 345 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL );
342 ::close( fd ); 346 ::close( fd );
343 347
344 QAsciiDict<int> dict(FExceptions+1); 348 QAsciiDict<int> dict(FExceptions+1);
345 dict.setAutoDelete( true ); 349 dict.setAutoDelete( true );
346 dict.insert( "description", new int(FDescription) ); 350 dict.insert( "description", new int(FDescription) );
347 dict.insert( "location", new int(FLocation) ); 351 dict.insert( "location", new int(FLocation) );
348 dict.insert( "categories", new int(FCategories) ); 352 dict.insert( "categories", new int(FCategories) );
349 dict.insert( "uid", new int(FUid) ); 353 dict.insert( "uid", new int(FUid) );
350 dict.insert( "type", new int(FType) ); 354 dict.insert( "type", new int(FType) );
351 dict.insert( "alarm", new int(FAlarm) ); 355 dict.insert( "alarm", new int(FAlarm) );
352 dict.insert( "sound", new int(FSound) ); 356 dict.insert( "sound", new int(FSound) );
353 dict.insert( "rtype", new int(FRType) ); 357 dict.insert( "rtype", new int(FRType) );
354 dict.insert( "rweekdays", new int(FRWeekdays) ); 358 dict.insert( "rweekdays", new int(FRWeekdays) );
355 dict.insert( "rposition", new int(FRPosition) ); 359 dict.insert( "rposition", new int(FRPosition) );
356 dict.insert( "rfreq", new int(FRFreq) ); 360 dict.insert( "rfreq", new int(FRFreq) );
357 dict.insert( "rhasenddate", new int(FRHasEndDate) ); 361 dict.insert( "rhasenddate", new int(FRHasEndDate) );
358 dict.insert( "enddt", new int(FREndDate) ); 362 dict.insert( "enddt", new int(FREndDate) );
359 dict.insert( "start", new int(FRStart) ); 363 dict.insert( "start", new int(FRStart) );
360 dict.insert( "end", new int(FREnd) ); 364 dict.insert( "end", new int(FREnd) );
361 dict.insert( "note", new int(FNote) ); 365 dict.insert( "note", new int(FNote) );
362 dict.insert( "created", new int(FCreated) ); 366 dict.insert( "created", new int(FCreated) ); // Shouldn't this be FRCreated ??
363 dict.insert( "recparent", new int(FRecParent) ); 367 dict.insert( "recparent", new int(FRecParent) );
364 dict.insert( "recchildren", new int(FRecChildren) ); 368 dict.insert( "recchildren", new int(FRecChildren) );
365 dict.insert( "exceptions", new int(FExceptions) ); 369 dict.insert( "exceptions", new int(FExceptions) );
366 dict.insert( "timezone", new int(FTimeZone) ); 370 dict.insert( "timezone", new int(FTimeZone) );
367 371
368 char* dt = (char*)map_addr; 372 char* dt = (char*)map_addr;
369 int len = attribute.st_size; 373 int len = attribute.st_size;
370 int i = 0; 374 int i = 0;
371 char* point; 375 char* point;
372 const char* collectionString = "<event "; 376 const char* collectionString = "<event ";
373 int strLen = ::strlen(collectionString); 377 int strLen = ::strlen(collectionString);
374 int *find; 378 int *find;
375 while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) { 379 while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) {
376 i = point -dt; 380 i = point -dt;
377 i+= strLen; 381 i+= strLen;
378 382
379 alarmTime = -1; 383 alarmTime = -1;
380 snd = 0; // silent 384 snd = 0; // silent
381 385
382 OEvent ev; 386 OEvent ev;
383 rec = 0; 387 rec = 0;
384 388
385 while ( TRUE ) { 389 while ( TRUE ) {
386 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 390 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
387 ++i; 391 ++i;
388 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 392 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
389 break; 393 break;
390 394
391 395
392 // we have another attribute, read it. 396 // we have another attribute, read it.
393 int j = i; 397 int j = i;
394 while ( j < len && dt[j] != '=' ) 398 while ( j < len && dt[j] != '=' )
395 ++j; 399 ++j;
396 QCString attr( dt+i, j-i+1); 400 QCString attr( dt+i, j-i+1);
397 401
398 i = ++j; // skip = 402 i = ++j; // skip =
399 403
400 // find the start of quotes 404 // find the start of quotes
401 while ( i < len && dt[i] != '"' ) 405 while ( i < len && dt[i] != '"' )
402 ++i; 406 ++i;
403 j = ++i; 407 j = ++i;
404 408
405 bool haveUtf = FALSE; 409 bool haveUtf = FALSE;
406 bool haveEnt = FALSE; 410 bool haveEnt = FALSE;
407 while ( j < len && dt[j] != '"' ) { 411 while ( j < len && dt[j] != '"' ) {
408 if ( ((unsigned char)dt[j]) > 0x7f ) 412 if ( ((unsigned char)dt[j]) > 0x7f )
409 haveUtf = TRUE; 413 haveUtf = TRUE;
410 if ( dt[j] == '&' ) 414 if ( dt[j] == '&' )
411 haveEnt = TRUE; 415 haveEnt = TRUE;
412 ++j; 416 ++j;
413 } 417 }
414 if ( i == j ) { 418 if ( i == j ) {
415 // empty value 419 // empty value
416 i = j + 1; 420 i = j + 1;
417 continue; 421 continue;
418 } 422 }
419 423
420 QCString value( dt+i, j-i+1 ); 424 QCString value( dt+i, j-i+1 );
421 i = j + 1; 425 i = j + 1;
422 426
423 QString str = (haveUtf ? QString::fromUtf8( value ) 427 QString str = (haveUtf ? QString::fromUtf8( value )
424 : QString::fromLatin1( value ) ); 428 : QString::fromLatin1( value ) );
425 if ( haveEnt ) 429 if ( haveEnt )
426 str = Qtopia::plainString( str ); 430 str = Qtopia::plainString( str );
427 431
428 /* 432 /*
429 * add key + value 433 * add key + value
430 */ 434 */
431 find = dict[attr.data()]; 435 find = dict[attr.data()];
432 if (!find) 436 if (!find)
433 ev.setCustomField( attr, str ); 437 ev.setCustomField( attr, str );
434 else { 438 else {
435 setField( ev, *find, str ); 439 setField( ev, *find, str );
436 } 440 }
437 } 441 }
438 /* time to finalize */ 442 /* time to finalize */
439 finalizeRecord( ev ); 443 finalizeRecord( ev );
440 delete rec; 444 delete rec;
441 } 445 }
442 ::munmap(map_addr, attribute.st_size ); 446 ::munmap(map_addr, attribute.st_size );
443 m_changed = false; // changed during add 447 m_changed = false; // changed during add
444 448
445 return true; 449 return true;
446} 450}
451
452// FIXME: Use OEvent::fromMap() which makes this obsolete.. (eilers)
447void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { 453void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) {
448 /* AllDay is alway in UTC */ 454 /* AllDay is alway in UTC */
449 if ( ev.isAllDay() ) { 455 if ( ev.isAllDay() ) {
450 OTimeZone utc = OTimeZone::utc(); 456 OTimeZone utc = OTimeZone::utc();
451 ev.setStartDateTime( utc.fromUTCDateTime( start ) ); 457 ev.setStartDateTime( utc.fromUTCDateTime( start ) );
452 ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); 458 ev.setEndDateTime ( utc.fromUTCDateTime( end ) );
453 ev.setTimeZone( "UTC"); // make sure it is really utc 459 ev.setTimeZone( "UTC"); // make sure it is really utc
454 }else { 460 }else {
455 /* to current date time */ 461 /* to current date time */
456 // qWarning(" Start is %d", start ); 462 // qWarning(" Start is %d", start );
457 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); 463 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
458 QDateTime date = zone.toDateTime( start ); 464 QDateTime date = zone.toDateTime( start );
459 qWarning(" Start is %s", date.toString().latin1() ); 465 qWarning(" Start is %s", date.toString().latin1() );
460 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) ); 466 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
461 467
462 date = zone.toDateTime( end ); 468 date = zone.toDateTime( end );
463 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) ); 469 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
464 } 470 }
465 if ( rec && rec->doesRecur() ) { 471 if ( rec && rec->doesRecur() ) {
466 OTimeZone utc = OTimeZone::utc(); 472 OTimeZone utc = OTimeZone::utc();
467 ORecur recu( *rec ); // call copy c'tor; 473 ORecur recu( *rec ); // call copy c'tor;
468 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() ); 474 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() );
469 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) ); 475 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) );
470 recu.setStart( ev.startDateTime().date() ); 476 recu.setStart( ev.startDateTime().date() );
471 ev.setRecurrence( recu ); 477 ev.setRecurrence( recu );
472 } 478 }
473 479
474 if (alarmTime != -1 ) { 480 if (alarmTime != -1 ) {
475 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); 481 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 );
476 OPimAlarm al( snd , dt ); 482 OPimAlarm al( snd , dt );
477 ev.notifiers().add( al ); 483 ev.notifiers().add( al );
478 } 484 }
479 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { 485 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) {
480 qWarning("already contains assign uid"); 486 qWarning("already contains assign uid");
481 ev.setUid( 1 ); 487 ev.setUid( 1 );
482 } 488 }
483 qWarning("addind %d %s", ev.uid(), ev.description().latin1() ); 489 qWarning("addind %d %s", ev.uid(), ev.description().latin1() );
484 if ( ev.hasRecurrence() ) 490 if ( ev.hasRecurrence() )
485 m_rep.insert( ev.uid(), ev ); 491 m_rep.insert( ev.uid(), ev );
486 else 492 else
487 m_raw.insert( ev.uid(), ev ); 493 m_raw.insert( ev.uid(), ev );
488 494
489} 495}
490void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) { 496void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) {
491// qWarning(" setting %s", value.latin1() ); 497// qWarning(" setting %s", value.latin1() );
492 switch( id ) { 498 switch( id ) {
493 case FDescription: 499 case FDescription:
494 e.setDescription( value ); 500 e.setDescription( value );
495 break; 501 break;
496 case FLocation: 502 case FLocation:
497 e.setLocation( value ); 503 e.setLocation( value );
498 break; 504 break;
499 case FCategories: 505 case FCategories:
500 e.setCategories( e.idsFromString( value ) ); 506 e.setCategories( e.idsFromString( value ) );
501 break; 507 break;
502 case FUid: 508 case FUid:
503 e.setUid( value.toInt() ); 509 e.setUid( value.toInt() );
504 break; 510 break;
505 case FType: 511 case FType:
506 if ( value == "AllDay" ) { 512 if ( value == "AllDay" ) {
507 e.setAllDay( true ); 513 e.setAllDay( true );
508 e.setTimeZone( "UTC" ); 514 e.setTimeZone( "UTC" );
509 } 515 }
510 break; 516 break;
511 case FAlarm: 517 case FAlarm:
512 alarmTime = value.toInt(); 518 alarmTime = value.toInt();
513 break; 519 break;
514 case FSound: 520 case FSound:
515 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; 521 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent;
516 break; 522 break;
517 // recurrence stuff 523 // recurrence stuff
518 case FRType: 524 case FRType:
519 if ( value == "Daily" ) 525 if ( value == "Daily" )
520 recur()->setType( ORecur::Daily ); 526 recur()->setType( ORecur::Daily );
521 else if ( value == "Weekly" ) 527 else if ( value == "Weekly" )
522 recur()->setType( ORecur::Weekly); 528 recur()->setType( ORecur::Weekly);
523 else if ( value == "MonthlyDay" ) 529 else if ( value == "MonthlyDay" )
524 recur()->setType( ORecur::MonthlyDay ); 530 recur()->setType( ORecur::MonthlyDay );
525 else if ( value == "MonthlyDate" ) 531 else if ( value == "MonthlyDate" )
526 recur()->setType( ORecur::MonthlyDate ); 532 recur()->setType( ORecur::MonthlyDate );
527 else if ( value == "Yearly" ) 533 else if ( value == "Yearly" )
528 recur()->setType( ORecur::Yearly ); 534 recur()->setType( ORecur::Yearly );
529 else 535 else
530 recur()->setType( ORecur::NoRepeat ); 536 recur()->setType( ORecur::NoRepeat );
531 break; 537 break;
532 case FRWeekdays: 538 case FRWeekdays:
533 recur()->setDays( value.toInt() ); 539 recur()->setDays( value.toInt() );
534 break; 540 break;
535 case FRPosition: 541 case FRPosition:
536 recur()->setPosition( value.toInt() ); 542 recur()->setPosition( value.toInt() );
537 break; 543 break;
538 case FRFreq: 544 case FRFreq:
539 recur()->setFrequency( value.toInt() ); 545 recur()->setFrequency( value.toInt() );
540 break; 546 break;
541 case FRHasEndDate: 547 case FRHasEndDate:
542 recur()->setHasEndDate( value.toInt() ); 548 recur()->setHasEndDate( value.toInt() );
543 break; 549 break;
544 case FREndDate: { 550 case FREndDate: {
545 rp_end = (time_t) value.toLong(); 551 rp_end = (time_t) value.toLong();
546 break; 552 break;
547 } 553 }
548 case FRStart: { 554 case FRStart: {
549 start = (time_t) value.toLong(); 555 start = (time_t) value.toLong();
550 break; 556 break;
551 } 557 }
552 case FREnd: { 558 case FREnd: {
553 end = ( (time_t) value.toLong() ); 559 end = ( (time_t) value.toLong() );
554 break; 560 break;
555 } 561 }
556 case FNote: 562 case FNote:
557 e.setNote( value ); 563 e.setNote( value );
558 break; 564 break;
559 case FCreated: 565 case FCreated:
560 created = value.toInt(); 566 created = value.toInt();
561 break; 567 break;
562 case FRecParent: 568 case FRecParent:
563 e.setParent( value.toInt() ); 569 e.setParent( value.toInt() );
564 break; 570 break;
565 case FRecChildren:{ 571 case FRecChildren:{
566 QStringList list = QStringList::split(' ', value ); 572 QStringList list = QStringList::split(' ', value );
567 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { 573 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
568 e.addChild( (*it).toInt() ); 574 e.addChild( (*it).toInt() );
569 } 575 }
570 } 576 }
571 break; 577 break;
572 case FExceptions:{ 578 case FExceptions:{
573 QStringList list = QStringList::split(' ', value ); 579 QStringList list = QStringList::split(' ', value );
574 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { 580 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
575 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() ); 581 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() );
576 qWarning("adding exception %s", date.toString().latin1() ); 582 qWarning("adding exception %s", date.toString().latin1() );
577 recur()->exceptions().append( date ); 583 recur()->exceptions().append( date );
578 } 584 }
579 } 585 }
580 break; 586 break;
581 case FTimeZone: 587 case FTimeZone:
582 if ( value != "None" ) 588 if ( value != "None" )
583 e.setTimeZone( value ); 589 e.setTimeZone( value );
584 break; 590 break;
585 default: 591 default:
586 break; 592 break;
587 } 593 }
588} 594}
589QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const 595QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const
590{ 596{
591 QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() ); 597 QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() );
592 uint arraycounter = 0; 598 uint arraycounter = 0;
593 QMap<int, OEvent>::ConstIterator it; 599 QMap<int, OEvent>::ConstIterator it;
594 600
595 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) 601 for ( it = m_raw.begin(); it != m_raw.end(); ++it )
596 if ( it.data().match( r ) ) 602 if ( it.data().match( r ) )
597 m_currentQuery[arraycounter++] = it.data().uid(); 603 m_currentQuery[arraycounter++] = it.data().uid();
598 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) 604 for ( it = m_rep.begin(); it != m_rep.end(); ++it )
599 if ( it.data().match( r ) ) 605 if ( it.data().match( r ) )
600 m_currentQuery[arraycounter++] = it.data().uid(); 606 m_currentQuery[arraycounter++] = it.data().uid();
601 607
602 // Shrink to fit.. 608 // Shrink to fit..
603 m_currentQuery.resize(arraycounter); 609 m_currentQuery.resize(arraycounter);
604 610
605 return m_currentQuery; 611 return m_currentQuery;
606} 612}
diff --git a/libopie/pim/oevent.cpp b/libopie/pim/oevent.cpp
index 7bcf944..c916297 100644
--- a/libopie/pim/oevent.cpp
+++ b/libopie/pim/oevent.cpp
@@ -1,577 +1,704 @@
1#include <qshared.h> 1#include <qshared.h>
2#include <qarray.h>
2 3
3#include <qpe/palmtopuidgen.h> 4#include <qpe/palmtopuidgen.h>
4#include <qpe/categories.h> 5#include <qpe/categories.h>
5#include <qpe/stringutil.h> 6#include <qpe/stringutil.h>
6 7
7#include "orecur.h" 8#include "orecur.h"
8#include "opimresolver.h" 9#include "opimresolver.h"
9#include "opimnotifymanager.h" 10#include "opimnotifymanager.h"
10 11
11#include "oevent.h" 12#include "oevent.h"
12 13
13int OCalendarHelper::week( const QDate& date) { 14int OCalendarHelper::week( const QDate& date) {
14 // Calculates the week this date is in within that 15 // Calculates the week this date is in within that
15 // month. Equals the "row" is is in in the month view 16 // month. Equals the "row" is is in in the month view
16 int week = 1; 17 int week = 1;
17 QDate tmp( date.year(), date.month(), 1 ); 18 QDate tmp( date.year(), date.month(), 1 );
18 if ( date.dayOfWeek() < tmp.dayOfWeek() ) 19 if ( date.dayOfWeek() < tmp.dayOfWeek() )
19 ++week; 20 ++week;
20 21
21 week += ( date.day() - 1 ) / 7; 22 week += ( date.day() - 1 ) / 7;
22 23
23 return week; 24 return week;
24} 25}
25int OCalendarHelper::ocurrence( const QDate& date) { 26int OCalendarHelper::ocurrence( const QDate& date) {
26 // calculates the number of occurrances of this day of the 27 // calculates the number of occurrances of this day of the
27 // week till the given date (e.g 3rd Wednesday of the month) 28 // week till the given date (e.g 3rd Wednesday of the month)
28 return ( date.day() - 1 ) / 7 + 1; 29 return ( date.day() - 1 ) / 7 + 1;
29} 30}
30int OCalendarHelper::dayOfWeek( char day ) { 31int OCalendarHelper::dayOfWeek( char day ) {
31 int dayOfWeek = 1; 32 int dayOfWeek = 1;
32 char i = ORecur::MON; 33 char i = ORecur::MON;
33 while ( !( i & day ) && i <= ORecur::SUN ) { 34 while ( !( i & day ) && i <= ORecur::SUN ) {
34 i <<= 1; 35 i <<= 1;
35 ++dayOfWeek; 36 ++dayOfWeek;
36 } 37 }
37 return dayOfWeek; 38 return dayOfWeek;
38} 39}
39int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) { 40int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) {
40 return ( second.year() - first.year() ) * 12 + 41 return ( second.year() - first.year() ) * 12 +
41 second.month() - first.month(); 42 second.month() - first.month();
42} 43}
43 44
44struct OEvent::Data : public QShared { 45struct OEvent::Data : public QShared {
45 Data() : QShared() { 46 Data() : QShared() {
46 child = 0; 47 child = 0;
47 recur = 0; 48 recur = 0;
48 manager = 0; 49 manager = 0;
49 isAllDay = false; 50 isAllDay = false;
50 parent = 0; 51 parent = 0;
51 } 52 }
52 ~Data() { 53 ~Data() {
53 delete manager; 54 delete manager;
54 delete recur; 55 delete recur;
55 } 56 }
56 QString description; 57 QString description;
57 QString location; 58 QString location;
58 OPimNotifyManager* manager; 59 OPimNotifyManager* manager;
59 ORecur* recur; 60 ORecur* recur;
60 QString note; 61 QString note;
61 QDateTime created; 62 QDateTime created;
62 QDateTime start; 63 QDateTime start;
63 QDateTime end; 64 QDateTime end;
64 bool isAllDay : 1; 65 bool isAllDay : 1;
65 QString timezone; 66 QString timezone;
66 QArray<int>* child; 67 QArray<int>* child;
67 int parent; 68 int parent;
68}; 69};
69 70
70OEvent::OEvent( int uid ) 71OEvent::OEvent( int uid )
71 : OPimRecord( uid ) { 72 : OPimRecord( uid ) {
72 data = new Data; 73 data = new Data;
73} 74}
74OEvent::OEvent( const OEvent& ev) 75OEvent::OEvent( const OEvent& ev)
75 : OPimRecord( ev ), data( ev.data ) 76 : OPimRecord( ev ), data( ev.data )
76{ 77{
77 data->ref(); 78 data->ref();
78} 79}
79OEvent::~OEvent() { 80OEvent::~OEvent() {
80 if ( data->deref() ) { 81 if ( data->deref() ) {
81 delete data; 82 delete data;
82 data = 0; 83 data = 0;
83 } 84 }
84} 85}
85OEvent& OEvent::operator=( const OEvent& ev) { 86OEvent& OEvent::operator=( const OEvent& ev) {
86 if ( this == &ev ) return *this; 87 if ( this == &ev ) return *this;
87 88
88 OPimRecord::operator=( ev ); 89 OPimRecord::operator=( ev );
89 ev.data->ref(); 90 ev.data->ref();
90 deref(); 91 deref();
91 data = ev.data; 92 data = ev.data;
92 93
93 94
94 return *this; 95 return *this;
95} 96}
96QString OEvent::description()const { 97QString OEvent::description()const {
97 return data->description; 98 return data->description;
98} 99}
99void OEvent::setDescription( const QString& description ) { 100void OEvent::setDescription( const QString& description ) {
100 changeOrModify(); 101 changeOrModify();
101 data->description = description; 102 data->description = description;
102} 103}
103void OEvent::setLocation( const QString& loc ) { 104void OEvent::setLocation( const QString& loc ) {
104 changeOrModify(); 105 changeOrModify();
105 data->location = loc; 106 data->location = loc;
106} 107}
107QString OEvent::location()const { 108QString OEvent::location()const {
108 return data->location; 109 return data->location;
109} 110}
110OPimNotifyManager &OEvent::notifiers()const { 111OPimNotifyManager &OEvent::notifiers()const {
111 // I hope we can skip the changeOrModify here 112 // I hope we can skip the changeOrModify here
112 // the notifier should take care of it 113 // the notifier should take care of it
113 // and OPimNotify is shared too 114 // and OPimNotify is shared too
114 if (!data->manager ) 115 if (!data->manager )
115 data->manager = new OPimNotifyManager; 116 data->manager = new OPimNotifyManager;
116 117
117 return *data->manager; 118 return *data->manager;
118} 119}
119bool OEvent::hasNotifiers()const { 120bool OEvent::hasNotifiers()const {
120 if (!data->manager ) 121 if (!data->manager )
121 return false; 122 return false;
122 if (data->manager->reminders().isEmpty() && 123 if (data->manager->reminders().isEmpty() &&
123 data->manager->alarms().isEmpty() ) 124 data->manager->alarms().isEmpty() )
124 return false; 125 return false;
125 126
126 return true; 127 return true;
127} 128}
128ORecur OEvent::recurrence()const { 129ORecur OEvent::recurrence()const {
129 if (!data->recur) 130 if (!data->recur)
130 data->recur = new ORecur; 131 data->recur = new ORecur;
131 132
132 return *data->recur; 133 return *data->recur;
133} 134}
134void OEvent::setRecurrence( const ORecur& rec) { 135void OEvent::setRecurrence( const ORecur& rec) {
135 changeOrModify(); 136 changeOrModify();
136 if (data->recur ) 137 if (data->recur )
137 (*data->recur) = rec; 138 (*data->recur) = rec;
138 else 139 else
139 data->recur = new ORecur( rec ); 140 data->recur = new ORecur( rec );
140} 141}
141bool OEvent::hasRecurrence()const { 142bool OEvent::hasRecurrence()const {
142 if (!data->recur ) return false; 143 if (!data->recur ) return false;
143 return data->recur->doesRecur(); 144 return data->recur->doesRecur();
144} 145}
145QString OEvent::note()const { 146QString OEvent::note()const {
146 return data->note; 147 return data->note;
147} 148}
148void OEvent::setNote( const QString& note ) { 149void OEvent::setNote( const QString& note ) {
149 changeOrModify(); 150 changeOrModify();
150 data->note = note; 151 data->note = note;
151} 152}
152QDateTime OEvent::createdDateTime()const { 153QDateTime OEvent::createdDateTime()const {
153 return data->created; 154 return data->created;
154} 155}
155void OEvent::setCreatedDateTime( const QDateTime& time ) { 156void OEvent::setCreatedDateTime( const QDateTime& time ) {
156 changeOrModify(); 157 changeOrModify();
157 data->created = time; 158 data->created = time;
158} 159}
159QDateTime OEvent::startDateTime()const { 160QDateTime OEvent::startDateTime()const {
160 if ( data->isAllDay ) 161 if ( data->isAllDay )
161 return QDateTime( data->start.date(), QTime(0, 0, 0 ) ); 162 return QDateTime( data->start.date(), QTime(0, 0, 0 ) );
162 return data->start; 163 return data->start;
163} 164}
164QDateTime OEvent::startDateTimeInZone()const { 165QDateTime OEvent::startDateTimeInZone()const {
165 /* if no timezone, or all day event or if the current and this timeZone match... */ 166 /* if no timezone, or all day event or if the current and this timeZone match... */
166 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime(); 167 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime();
167 168
168 OTimeZone zone(data->timezone ); 169 OTimeZone zone(data->timezone );
169 return zone.toDateTime( data->start, OTimeZone::current() ); 170 return zone.toDateTime( data->start, OTimeZone::current() );
170} 171}
171void OEvent::setStartDateTime( const QDateTime& dt ) { 172void OEvent::setStartDateTime( const QDateTime& dt ) {
172 changeOrModify(); 173 changeOrModify();
173 data->start = dt; 174 data->start = dt;
174} 175}
175QDateTime OEvent::endDateTime()const { 176QDateTime OEvent::endDateTime()const {
176 /* 177 /*
177 * if all Day event the end time needs 178 * if all Day event the end time needs
178 * to be on the same day as the start 179 * to be on the same day as the start
179 */ 180 */
180 if ( data->isAllDay ) 181 if ( data->isAllDay )
181 return QDateTime( data->start.date(), QTime(23, 59, 59 ) ); 182 return QDateTime( data->start.date(), QTime(23, 59, 59 ) );
182 return data->end; 183 return data->end;
183} 184}
184QDateTime OEvent::endDateTimeInZone()const { 185QDateTime OEvent::endDateTimeInZone()const {
185 /* if no timezone, or all day event or if the current and this timeZone match... */ 186 /* if no timezone, or all day event or if the current and this timeZone match... */
186 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime(); 187 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime();
187 188
188 OTimeZone zone(data->timezone ); 189 OTimeZone zone(data->timezone );
189 return zone.toDateTime( data->end, OTimeZone::current() ); 190 return zone.toDateTime( data->end, OTimeZone::current() );
190} 191}
191void OEvent::setEndDateTime( const QDateTime& dt ) { 192void OEvent::setEndDateTime( const QDateTime& dt ) {
192 changeOrModify(); 193 changeOrModify();
193 data->end = dt; 194 data->end = dt;
194} 195}
195bool OEvent::isMultipleDay()const { 196bool OEvent::isMultipleDay()const {
196 return data->end.date().day() - data->start.date().day(); 197 return data->end.date().day() - data->start.date().day();
197} 198}
198bool OEvent::isAllDay()const { 199bool OEvent::isAllDay()const {
199 return data->isAllDay; 200 return data->isAllDay;
200} 201}
201void OEvent::setAllDay( bool allDay ) { 202void OEvent::setAllDay( bool allDay ) {
202 changeOrModify(); 203 changeOrModify();
203 data->isAllDay = allDay; 204 data->isAllDay = allDay;
204 if (allDay ) data->timezone = "UTC"; 205 if (allDay ) data->timezone = "UTC";
205} 206}
206void OEvent::setTimeZone( const QString& tz ) { 207void OEvent::setTimeZone( const QString& tz ) {
207 changeOrModify(); 208 changeOrModify();
208 data->timezone = tz; 209 data->timezone = tz;
209} 210}
210QString OEvent::timeZone()const { 211QString OEvent::timeZone()const {
211 if (data->isAllDay ) return QString::fromLatin1("UTC"); 212 if (data->isAllDay ) return QString::fromLatin1("UTC");
212 return data->timezone; 213 return data->timezone;
213} 214}
214bool OEvent::match( const QRegExp& re )const { 215bool OEvent::match( const QRegExp& re )const {
215 if ( re.match( data->description ) != -1 ){ 216 if ( re.match( data->description ) != -1 ){
216 setLastHitField( Qtopia::DatebookDescription ); 217 setLastHitField( Qtopia::DatebookDescription );
217 return true; 218 return true;
218 } 219 }
219 if ( re.match( data->note ) != -1 ){ 220 if ( re.match( data->note ) != -1 ){
220 setLastHitField( Qtopia::Note ); 221 setLastHitField( Qtopia::Note );
221 return true; 222 return true;
222 } 223 }
223 if ( re.match( data->location ) != -1 ){ 224 if ( re.match( data->location ) != -1 ){
224 setLastHitField( Qtopia::Location ); 225 setLastHitField( Qtopia::Location );
225 return true; 226 return true;
226 } 227 }
227 if ( re.match( data->start.toString() ) != -1 ){ 228 if ( re.match( data->start.toString() ) != -1 ){
228 setLastHitField( Qtopia::StartDateTime ); 229 setLastHitField( Qtopia::StartDateTime );
229 return true; 230 return true;
230 } 231 }
231 if ( re.match( data->end.toString() ) != -1 ){ 232 if ( re.match( data->end.toString() ) != -1 ){
232 setLastHitField( Qtopia::EndDateTime ); 233 setLastHitField( Qtopia::EndDateTime );
233 return true; 234 return true;
234 } 235 }
235 return false; 236 return false;
236} 237}
237QString OEvent::toRichText()const { 238QString OEvent::toRichText()const {
238 QString text, value; 239 QString text, value;
239 240
240 // description 241 // description
241 text += "<b><h3><img src=\"datebook/DateBook\">"; 242 text += "<b><h3><img src=\"datebook/DateBook\">";
242 if ( !description().isEmpty() ) { 243 if ( !description().isEmpty() ) {
243 text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "" ); 244 text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "" );
244 } 245 }
245 text += "</h3></b><br><hr><br>"; 246 text += "</h3></b><br><hr><br>";
246 247
247 // location 248 // location
248 if ( !(value = location()).isEmpty() ) { 249 if ( !(value = location()).isEmpty() ) {
249 text += "<b>" + QObject::tr( "Location:" ) + "</b> "; 250 text += "<b>" + QObject::tr( "Location:" ) + "</b> ";
250 text += Qtopia::escapeString(value) + "<br>"; 251 text += Qtopia::escapeString(value) + "<br>";
251 } 252 }
252 253
253 // all day event 254 // all day event
254 if ( isAllDay() ) { 255 if ( isAllDay() ) {
255 text += "<b><i>" + QObject::tr( "This is an all day event" ) + "</i></b><br>"; 256 text += "<b><i>" + QObject::tr( "This is an all day event" ) + "</i></b><br>";
256 } 257 }
257 // multiple day event 258 // multiple day event
258 else if ( isMultipleDay () ) { 259 else if ( isMultipleDay () ) {
259 text += "<b><i>" + QObject::tr( "This is a multiple day event" ) + "</i></b><br>"; 260 text += "<b><i>" + QObject::tr( "This is a multiple day event" ) + "</i></b><br>";
260 } 261 }
261 // start & end times 262 // start & end times
262 else { 263 else {
263 // start time 264 // start time
264 if ( startDateTime().isValid() ) { 265 if ( startDateTime().isValid() ) {
265 text += "<b>" + QObject::tr( "Start:") + "</b> "; 266 text += "<b>" + QObject::tr( "Start:") + "</b> ";
266 text += Qtopia::escapeString(startDateTime().toString() ). 267 text += Qtopia::escapeString(startDateTime().toString() ).
267 replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; 268 replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
268 } 269 }
269 270
270 // end time 271 // end time
271 if ( endDateTime().isValid() ) { 272 if ( endDateTime().isValid() ) {
272 text += "<b>" + QObject::tr( "End:") + "</b> "; 273 text += "<b>" + QObject::tr( "End:") + "</b> ";
273 text += Qtopia::escapeString(endDateTime().toString() ). 274 text += Qtopia::escapeString(endDateTime().toString() ).
274 replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; 275 replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
275 } 276 }
276 } 277 }
277 278
278 // categories 279 // categories
279 if ( categoryNames("Calendar").count() ){ 280 if ( categoryNames("Calendar").count() ){
280 text += "<b>" + QObject::tr( "Category:") + "</b> "; 281 text += "<b>" + QObject::tr( "Category:") + "</b> ";
281 text += categoryNames("Calendar").join(", "); 282 text += categoryNames("Calendar").join(", ");
282 text += "<br>"; 283 text += "<br>";
283 } 284 }
284 285
285 //notes 286 //notes
286 if ( !note().isEmpty() ) { 287 if ( !note().isEmpty() ) {
287 text += "<b>" + QObject::tr( "Note:") + "</b><br>"; 288 text += "<b>" + QObject::tr( "Note:") + "</b><br>";
288 text += note(); 289 text += note();
289// text += Qtopia::escapeString(note() ). 290// text += Qtopia::escapeString(note() ).
290// replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; 291// replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
291 } 292 }
292 return text; 293 return text;
293} 294}
294QString OEvent::toShortText()const { 295QString OEvent::toShortText()const {
295 QString text; 296 QString text;
296 text += QString::number( startDateTime().date().day() ); 297 text += QString::number( startDateTime().date().day() );
297 text += "."; 298 text += ".";
298 text += QString::number( startDateTime().date().month() ); 299 text += QString::number( startDateTime().date().month() );
299 text += "."; 300 text += ".";
300 text += QString::number( startDateTime().date().year() ); 301 text += QString::number( startDateTime().date().year() );
301 text += " "; 302 text += " ";
302 text += QString::number( startDateTime().time().hour() ); 303 text += QString::number( startDateTime().time().hour() );
303 text += ":"; 304 text += ":";
304 text += QString::number( startDateTime().time().minute() ); 305 text += QString::number( startDateTime().time().minute() );
305 text += " - "; 306 text += " - ";
306 text += description(); 307 text += description();
307 return text; 308 return text;
308} 309}
309QString OEvent::type()const { 310QString OEvent::type()const {
310 return QString::fromLatin1("OEvent"); 311 return QString::fromLatin1("OEvent");
311} 312}
312QString OEvent::recordField( int /*id */ )const { 313QString OEvent::recordField( int /*id */ )const {
313 return QString::null; 314 return QString::null;
314} 315}
315int OEvent::rtti() { 316int OEvent::rtti() {
316 return OPimResolver::DateBook; 317 return OPimResolver::DateBook;
317} 318}
318bool OEvent::loadFromStream( QDataStream& ) { 319bool OEvent::loadFromStream( QDataStream& ) {
319 return true; 320 return true;
320} 321}
321bool OEvent::saveToStream( QDataStream& )const { 322bool OEvent::saveToStream( QDataStream& )const {
322 return true; 323 return true;
323} 324}
324void OEvent::changeOrModify() { 325void OEvent::changeOrModify() {
325 if ( data->count != 1 ) { 326 if ( data->count != 1 ) {
326 data->deref(); 327 data->deref();
327 Data* d2 = new Data; 328 Data* d2 = new Data;
328 d2->description = data->description; 329 d2->description = data->description;
329 d2->location = data->location; 330 d2->location = data->location;
330 331
331 if (data->manager ) 332 if (data->manager )
332 d2->manager = new OPimNotifyManager( *data->manager ); 333 d2->manager = new OPimNotifyManager( *data->manager );
333 334
334 if ( data->recur ) 335 if ( data->recur )
335 d2->recur = new ORecur( *data->recur ); 336 d2->recur = new ORecur( *data->recur );
336 337
337 d2->note = data->note; 338 d2->note = data->note;
338 d2->created = data->created; 339 d2->created = data->created;
339 d2->start = data->start; 340 d2->start = data->start;
340 d2->end = data->end; 341 d2->end = data->end;
341 d2->isAllDay = data->isAllDay; 342 d2->isAllDay = data->isAllDay;
342 d2->timezone = data->timezone; 343 d2->timezone = data->timezone;
343 d2->parent = data->parent; 344 d2->parent = data->parent;
344 345
345 if ( data->child ) { 346 if ( data->child ) {
346 d2->child = new QArray<int>( *data->child ); 347 d2->child = new QArray<int>( *data->child );
347 d2->child->detach(); 348 d2->child->detach();
348 } 349 }
349 350
350 data = d2; 351 data = d2;
351 } 352 }
352} 353}
353void OEvent::deref() { 354void OEvent::deref() {
354 if ( data->deref() ) { 355 if ( data->deref() ) {
355 delete data; 356 delete data;
356 data = 0; 357 data = 0;
357 } 358 }
358} 359}
359// FIXME 360// Exporting Event data to map. Using the same
361// encoding as ODateBookAccessBackend_xml does..
362// Thus, we could remove the stuff there and use this
363// for it and for all other places..
364// Encoding should happen at one place, only ! (eilers)
360QMap<int, QString> OEvent::toMap()const { 365QMap<int, QString> OEvent::toMap()const {
361 return QMap<int, QString>(); 366 QMap<int, QString> retMap;
367
368 retMap.insert( OEvent::FUid, QString::number( uid() ) );
369 retMap.insert( OEvent::FCategories, Qtopia::escapeString( Qtopia::Record::idsToString( categories() ) ));
370 retMap.insert( OEvent::FDescription, Qtopia::escapeString( description() ) );
371 retMap.insert( OEvent::FLocation, Qtopia::escapeString( location() ) );
372 retMap.insert( OEvent::FType, isAllDay() ? "AllDay" : "" );
373 OPimAlarm alarm = notifiers().alarms()[0];
374 retMap.insert( OEvent::FAlarm, QString::number( alarm.dateTime().secsTo( startDateTime() ) / 60 ) );
375 retMap.insert( OEvent::FSound, (alarm.sound() == OPimAlarm::Loud) ? "loud" : "silent" );
376
377 OTimeZone zone( timeZone().isEmpty() ? OTimeZone::current() : timeZone() );
378 retMap.insert( OEvent::FStart, QString::number( zone.fromUTCDateTime( zone.toDateTime( startDateTime(), OTimeZone::utc() ) ) ) );
379 retMap.insert( OEvent::FEnd, QString::number( zone.fromUTCDateTime( zone.toDateTime( endDateTime(), OTimeZone::utc() ) ) ) );
380 retMap.insert( OEvent::FNote, Qtopia::escapeString( note() ) );
381 retMap.insert( OEvent::FTimeZone, timeZone().isEmpty() ? "None" : timeZone() );
382 if( parent() )
383 retMap.insert( OEvent::FRecParent, QString::number( parent() ) );
384 if( children().count() ){
385 QArray<int> childr = children();
386 QString buf;
387 for ( uint i = 0; i < childr.count(); i++ ) {
388 if ( i != 0 ) buf += " ";
389 buf += QString::number( childr[i] );
390 }
391 retMap.insert( OEvent::FRecChildren, buf );
392 }
393
394 // Add recurrence stuff
395 if( hasRecurrence() ){
396 ORecur recur = recurrence();
397 QMap<int, QString> recFields = recur.toMap();
398 retMap.insert( OEvent::FRType, recFields[ORecur::RType] );
399 retMap.insert( OEvent::FRWeekdays, recFields[ORecur::RWeekdays] );
400 retMap.insert( OEvent::FRPosition, recFields[ORecur::RPosition] );
401 retMap.insert( OEvent::FRFreq, recFields[ORecur::RFreq] );
402 retMap.insert( OEvent::FRHasEndDate, recFields[ORecur::RHasEndDate] );
403 retMap.insert( OEvent::FREndDate, recFields[ORecur::EndDate] );
404 retMap.insert( OEvent::FRCreated, recFields[ORecur::Created] );
405 retMap.insert( OEvent::FRExceptions, recFields[ORecur::Exceptions] );
406 }
407
408 return retMap;
409}
410
411void OEvent::fromMap( const QMap<int, QString>& map )
412{
413
414 // We just want to set the UID if it is really stored.
415 if ( !map[OEvent::FUid].isEmpty() )
416 setUid( map[OEvent::FUid].toInt() );
417
418 setCategories( idsFromString( map[OEvent::FCategories] ) );
419 setDescription( map[OEvent::FDescription] );
420 setLocation( map[OEvent::FLocation] );
421
422 if ( map[OEvent::FType] == "AllDay" )
423 setAllDay( true );
424 else
425 setAllDay( false );
426
427 int alarmTime = -1;
428 if( !map[OEvent::FAlarm].isEmpty() )
429 alarmTime = map[OEvent::FAlarm].toInt();
430
431 int sound = ( ( map[OEvent::FSound] == "loud" ) ? OPimAlarm::Loud : OPimAlarm::Silent );
432 if ( ( alarmTime != -1 ) ){
433 QDateTime dt = startDateTime().addSecs( -1*alarmTime*60 );
434 OPimAlarm al( sound , dt );
435 notifiers().add( al );
436 }
437 if ( !map[OEvent::FTimeZone].isEmpty() && ( map[OEvent::FTimeZone] != "None" ) ){
438 setTimeZone( map[OEvent::FTimeZone] );
439 }
440
441 time_t start = (time_t) map[OEvent::FStart].toLong();
442 time_t end = (time_t) map[OEvent::FEnd].toLong();
443
444 /* AllDay is always in UTC */
445 if ( isAllDay() ) {
446 OTimeZone utc = OTimeZone::utc();
447 setStartDateTime( utc.fromUTCDateTime( start ) );
448 setEndDateTime ( utc.fromUTCDateTime( end ) );
449 setTimeZone( "UTC"); // make sure it is really utc
450 }else {
451 /* to current date time */
452 // qWarning(" Start is %d", start );
453 OTimeZone zone( timeZone().isEmpty() ? OTimeZone::current() : timeZone() );
454 QDateTime date = zone.toDateTime( start );
455 qWarning(" Start is %s", date.toString().latin1() );
456 setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
457
458 date = zone.toDateTime( end );
459 setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
460 }
461
462 if ( !map[OEvent::FRecParent].isEmpty() )
463 setParent( map[OEvent::FRecParent].toInt() );
464
465 if ( !map[OEvent::FRecChildren].isEmpty() ){
466 QStringList list = QStringList::split(' ', map[OEvent::FRecChildren] );
467 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
468 addChild( (*it).toInt() );
469 }
470 }
471
472 // Fill recurrence stuff and put it directly into the ORecur-Object using fromMap..
473 if( !map[OEvent::FRType].isEmpty() ){
474 QMap<int, QString> recFields;
475 recFields.insert( ORecur::RType, map[OEvent::FRType] );
476 recFields.insert( ORecur::RWeekdays, map[OEvent::FRWeekdays] );
477 recFields.insert( ORecur::RPosition, map[OEvent::FRPosition] );
478 recFields.insert( ORecur::RFreq, map[OEvent::FRFreq] );
479 recFields.insert( ORecur::RHasEndDate, map[OEvent::FRHasEndDate] );
480 recFields.insert( ORecur::EndDate, map[OEvent::FREndDate] );
481 recFields.insert( ORecur::Created, map[OEvent::FRCreated] );
482 recFields.insert( ORecur::Exceptions, map[OEvent::FRExceptions] );
483 ORecur recur( recFields );
484 setRecurrence( recur );
485 }
486
362} 487}
488
489
363int OEvent::parent()const { 490int OEvent::parent()const {
364 return data->parent; 491 return data->parent;
365} 492}
366void OEvent::setParent( int uid ) { 493void OEvent::setParent( int uid ) {
367 changeOrModify(); 494 changeOrModify();
368 data->parent = uid; 495 data->parent = uid;
369} 496}
370QArray<int> OEvent::children() const{ 497QArray<int> OEvent::children() const{
371 if (!data->child) return QArray<int>(); 498 if (!data->child) return QArray<int>();
372 else 499 else
373 return data->child->copy(); 500 return data->child->copy();
374} 501}
375void OEvent::setChildren( const QArray<int>& arr ) { 502void OEvent::setChildren( const QArray<int>& arr ) {
376 changeOrModify(); 503 changeOrModify();
377 if (data->child) delete data->child; 504 if (data->child) delete data->child;
378 505
379 data->child = new QArray<int>( arr ); 506 data->child = new QArray<int>( arr );
380 data->child->detach(); 507 data->child->detach();
381} 508}
382void OEvent::addChild( int uid ) { 509void OEvent::addChild( int uid ) {
383 changeOrModify(); 510 changeOrModify();
384 if (!data->child ) { 511 if (!data->child ) {
385 data->child = new QArray<int>(1); 512 data->child = new QArray<int>(1);
386 (*data->child)[0] = uid; 513 (*data->child)[0] = uid;
387 }else{ 514 }else{
388 int count = data->child->count(); 515 int count = data->child->count();
389 data->child->resize( count + 1 ); 516 data->child->resize( count + 1 );
390 (*data->child)[count] = uid; 517 (*data->child)[count] = uid;
391 } 518 }
392} 519}
393void OEvent::removeChild( int uid ) { 520void OEvent::removeChild( int uid ) {
394 if (!data->child || !data->child->contains( uid ) ) return; 521 if (!data->child || !data->child->contains( uid ) ) return;
395 changeOrModify(); 522 changeOrModify();
396 QArray<int> newAr( data->child->count() - 1 ); 523 QArray<int> newAr( data->child->count() - 1 );
397 int j = 0; 524 int j = 0;
398 uint count = data->child->count(); 525 uint count = data->child->count();
399 for ( uint i = 0; i < count; i++ ) { 526 for ( uint i = 0; i < count; i++ ) {
400 if ( (*data->child)[i] != uid ) { 527 if ( (*data->child)[i] != uid ) {
401 newAr[j] = (*data->child)[i]; 528 newAr[j] = (*data->child)[i];
402 j++; 529 j++;
403 } 530 }
404 } 531 }
405 (*data->child) = newAr; 532 (*data->child) = newAr;
406} 533}
407struct OEffectiveEvent::Data : public QShared { 534struct OEffectiveEvent::Data : public QShared {
408 Data() : QShared() { 535 Data() : QShared() {
409 } 536 }
410 OEvent event; 537 OEvent event;
411 QDate date; 538 QDate date;
412 QTime start, end; 539 QTime start, end;
413 QDate startDate, endDate; 540 QDate startDate, endDate;
414 bool dates : 1; 541 bool dates : 1;
415}; 542};
416 543
417OEffectiveEvent::OEffectiveEvent() { 544OEffectiveEvent::OEffectiveEvent() {
418 data = new Data; 545 data = new Data;
419 data->date = QDate::currentDate(); 546 data->date = QDate::currentDate();
420 data->start = data->end = QTime::currentTime(); 547 data->start = data->end = QTime::currentTime();
421 data->dates = false; 548 data->dates = false;
422} 549}
423OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate, 550OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate,
424 Position pos ) { 551 Position pos ) {
425 data = new Data; 552 data = new Data;
426 data->event = ev; 553 data->event = ev;
427 data->date = startDate; 554 data->date = startDate;
428 if ( pos & Start ) 555 if ( pos & Start )
429 data->start = ev.startDateTime().time(); 556 data->start = ev.startDateTime().time();
430 else 557 else
431 data->start = QTime( 0, 0, 0 ); 558 data->start = QTime( 0, 0, 0 );
432 559
433 if ( pos & End ) 560 if ( pos & End )
434 data->end = ev.endDateTime().time(); 561 data->end = ev.endDateTime().time();
435 else 562 else
436 data->end = QTime( 23, 59, 59 ); 563 data->end = QTime( 23, 59, 59 );
437 564
438 data->dates = false; 565 data->dates = false;
439} 566}
440OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) { 567OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) {
441 data = ev.data; 568 data = ev.data;
442 data->ref(); 569 data->ref();
443} 570}
444OEffectiveEvent::~OEffectiveEvent() { 571OEffectiveEvent::~OEffectiveEvent() {
445 if ( data->deref() ) { 572 if ( data->deref() ) {
446 delete data; 573 delete data;
447 data = 0; 574 data = 0;
448 } 575 }
449} 576}
450OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) { 577OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) {
451 if ( *this == ev ) return *this; 578 if ( *this == ev ) return *this;
452 579
453 ev.data->ref(); 580 ev.data->ref();
454 deref(); 581 deref();
455 data = ev.data; 582 data = ev.data;
456 583
457 return *this; 584 return *this;
458} 585}
459 586
460void OEffectiveEvent::setStartTime( const QTime& ti) { 587void OEffectiveEvent::setStartTime( const QTime& ti) {
461 changeOrModify(); 588 changeOrModify();
462 data->start = ti; 589 data->start = ti;
463} 590}
464void OEffectiveEvent::setEndTime( const QTime& en) { 591void OEffectiveEvent::setEndTime( const QTime& en) {
465 changeOrModify(); 592 changeOrModify();
466 data->end = en; 593 data->end = en;
467} 594}
468void OEffectiveEvent::setEvent( const OEvent& ev) { 595void OEffectiveEvent::setEvent( const OEvent& ev) {
469 changeOrModify(); 596 changeOrModify();
470 data->event = ev; 597 data->event = ev;
471} 598}
472void OEffectiveEvent::setDate( const QDate& da) { 599void OEffectiveEvent::setDate( const QDate& da) {
473 changeOrModify(); 600 changeOrModify();
474 data->date = da; 601 data->date = da;
475} 602}
476void OEffectiveEvent::setEffectiveDates( const QDate& from, 603void OEffectiveEvent::setEffectiveDates( const QDate& from,
477 const QDate& to ) { 604 const QDate& to ) {
478 if (!from.isValid() ) { 605 if (!from.isValid() ) {
479 data->dates = false; 606 data->dates = false;
480 return; 607 return;
481 } 608 }
482 609
483 data->startDate = from; 610 data->startDate = from;
484 data->endDate = to; 611 data->endDate = to;
485} 612}
486QString OEffectiveEvent::description()const { 613QString OEffectiveEvent::description()const {
487 return data->event.description(); 614 return data->event.description();
488} 615}
489QString OEffectiveEvent::location()const { 616QString OEffectiveEvent::location()const {
490 return data->event.location(); 617 return data->event.location();
491} 618}
492QString OEffectiveEvent::note()const { 619QString OEffectiveEvent::note()const {
493 return data->event.note(); 620 return data->event.note();
494} 621}
495OEvent OEffectiveEvent::event()const { 622OEvent OEffectiveEvent::event()const {
496 return data->event; 623 return data->event;
497} 624}
498QTime OEffectiveEvent::startTime()const { 625QTime OEffectiveEvent::startTime()const {
499 return data->start; 626 return data->start;
500} 627}
501QTime OEffectiveEvent::endTime()const { 628QTime OEffectiveEvent::endTime()const {
502 return data->end; 629 return data->end;
503} 630}
504QDate OEffectiveEvent::date()const { 631QDate OEffectiveEvent::date()const {
505 return data->date; 632 return data->date;
506} 633}
507int OEffectiveEvent::length()const { 634int OEffectiveEvent::length()const {
508 return (data->end.hour() * 60 - data->start.hour() * 60) 635 return (data->end.hour() * 60 - data->start.hour() * 60)
509 + QABS(data->start.minute() - data->end.minute() ); 636 + QABS(data->start.minute() - data->end.minute() );
510} 637}
511int OEffectiveEvent::size()const { 638int OEffectiveEvent::size()const {
512 return ( data->end.hour() - data->start.hour() ) * 3600 639 return ( data->end.hour() - data->start.hour() ) * 3600
513 + (data->end.minute() - data->start.minute() * 60 640 + (data->end.minute() - data->start.minute() * 60
514 + data->end.second() - data->start.second() ); 641 + data->end.second() - data->start.second() );
515} 642}
516QDate OEffectiveEvent::startDate()const { 643QDate OEffectiveEvent::startDate()const {
517 if ( data->dates ) 644 if ( data->dates )
518 return data->startDate; 645 return data->startDate;
519 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer 646 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer
520 return data->date; 647 return data->date;
521 else 648 else
522 return data->event.startDateTime().date(); 649 return data->event.startDateTime().date();
523} 650}
524QDate OEffectiveEvent::endDate()const { 651QDate OEffectiveEvent::endDate()const {
525 if ( data->dates ) 652 if ( data->dates )
526 return data->endDate; 653 return data->endDate;
527 else if ( data->event.hasRecurrence() ) 654 else if ( data->event.hasRecurrence() )
528 return data->date; 655 return data->date;
529 else 656 else
530 return data->event.endDateTime().date(); 657 return data->event.endDateTime().date();
531} 658}
532void OEffectiveEvent::deref() { 659void OEffectiveEvent::deref() {
533 if ( data->deref() ) { 660 if ( data->deref() ) {
534 delete data; 661 delete data;
535 data = 0; 662 data = 0;
536 } 663 }
537} 664}
538void OEffectiveEvent::changeOrModify() { 665void OEffectiveEvent::changeOrModify() {
539 if ( data->count != 1 ) { 666 if ( data->count != 1 ) {
540 data->deref(); 667 data->deref();
541 Data* d2 = new Data; 668 Data* d2 = new Data;
542 d2->event = data->event; 669 d2->event = data->event;
543 d2->date = data->date; 670 d2->date = data->date;
544 d2->start = data->start; 671 d2->start = data->start;
545 d2->end = data->end; 672 d2->end = data->end;
546 d2->startDate = data->startDate; 673 d2->startDate = data->startDate;
547 d2->endDate = data->endDate; 674 d2->endDate = data->endDate;
548 d2->dates = data->dates; 675 d2->dates = data->dates;
549 data = d2; 676 data = d2;
550 } 677 }
551} 678}
552bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{ 679bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{
553 if ( data->date < e.date() ) 680 if ( data->date < e.date() )
554 return TRUE; 681 return TRUE;
555 if ( data->date == e.date() ) 682 if ( data->date == e.date() )
556 return ( startTime() < e.startTime() ); 683 return ( startTime() < e.startTime() );
557 else 684 else
558 return FALSE; 685 return FALSE;
559} 686}
560bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{ 687bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{
561 return (data->date <= e.date() ); 688 return (data->date <= e.date() );
562} 689}
563bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const { 690bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const {
564 return ( date() == e.date() 691 return ( date() == e.date()
565 && startTime() == e.startTime() 692 && startTime() == e.startTime()
566 && endTime()== e.endTime() 693 && endTime()== e.endTime()
567 && event() == e.event() ); 694 && event() == e.event() );
568} 695}
569bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const { 696bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const {
570 return !(*this == e ); 697 return !(*this == e );
571} 698}
572bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const { 699bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const {
573 return !(*this <= e ); 700 return !(*this <= e );
574} 701}
575bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const { 702bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const {
576 return !(*this < e); 703 return !(*this < e);
577} 704}
diff --git a/libopie/pim/oevent.h b/libopie/pim/oevent.h
index 30f442e..9218c97 100644
--- a/libopie/pim/oevent.h
+++ b/libopie/pim/oevent.h
@@ -1,220 +1,230 @@
1// CONTAINS GPLed code of TT 1// CONTAINS GPLed code of TT
2 2
3#ifndef OPIE_PIM_EVENT_H 3#ifndef OPIE_PIM_EVENT_H
4#define OPIE_PIM_EVENT_H 4#define OPIE_PIM_EVENT_H
5 5
6#include <qstring.h> 6#include <qstring.h>
7#include <qdatetime.h> 7#include <qdatetime.h>
8#include <qvaluelist.h> 8#include <qvaluelist.h>
9 9
10#include <qpe/recordfields.h> 10#include <qpe/recordfields.h>
11#include <qpe/palmtopuidgen.h> 11#include <qpe/palmtopuidgen.h>
12 12
13#include "otimezone.h" 13#include "otimezone.h"
14#include "opimrecord.h" 14#include "opimrecord.h"
15 15
16struct OCalendarHelper { 16struct OCalendarHelper {
17 /** calculate the week number of the date */ 17 /** calculate the week number of the date */
18 static int week( const QDate& ); 18 static int week( const QDate& );
19 /** calculate the occurence of week days since the start of the month */ 19 /** calculate the occurence of week days since the start of the month */
20 static int ocurrence( const QDate& ); 20 static int ocurrence( const QDate& );
21 21
22 // returns the dayOfWeek for the *first* day it finds (ignores 22 // returns the dayOfWeek for the *first* day it finds (ignores
23 // any further days!). Returns 1 (Monday) if there isn't any day found 23 // any further days!). Returns 1 (Monday) if there isn't any day found
24 static int dayOfWeek( char day ); 24 static int dayOfWeek( char day );
25 25
26 /** returns the diff of month */ 26 /** returns the diff of month */
27 static int monthDiff( const QDate& first, const QDate& second ); 27 static int monthDiff( const QDate& first, const QDate& second );
28 28
29}; 29};
30 30
31class OPimNotifyManager; 31class OPimNotifyManager;
32class ORecur; 32class ORecur;
33 33
34/** 34/**
35 * This is the container for all Events. It encapsules all 35 * This is the container for all Events. It encapsules all
36 * available information for a single Event 36 * available information for a single Event
37 * @short container for events. 37 * @short container for events.
38 */ 38 */
39class OEvent : public OPimRecord { 39class OEvent : public OPimRecord {
40public: 40public:
41 typedef QValueList<OEvent> ValueList; 41 typedef QValueList<OEvent> ValueList;
42 /** 42 /**
43 * RecordFields contain possible attributes 43 * RecordFields contain possible attributes
44 * used in the Results of toMap()..
44 */ 45 */
45 enum RecordFields { 46 enum RecordFields {
46 Uid = Qtopia::UID_ID, 47 FUid = Qtopia::UID_ID,
47 Category = Qtopia::CATEGORY_ID, 48 FCategories = Qtopia::CATEGORY_ID,
48 Description, 49 FDescription = 0,
49 Location, 50 FLocation,
50 Alarm, 51 FType,
51 Reminder, 52 FAlarm,
52 Recurrence, 53 FSound,
53 Note, 54 FRType,
54 Created, 55 FRWeekdays,
55 StartDate, 56 FRPosition,
56 EndDate, 57 FRFreq,
57 AllDay, 58 FRHasEndDate,
58 TimeZone 59 FREndDate,
60 FRCreated,
61 FRExceptions,
62 FStart,
63 FEnd,
64 FNote,
65 FTimeZone,
66 FRecParent,
67 FRecChildren,
59 }; 68 };
60 69
61 /** 70 /**
62 * Start with an Empty OEvent. UID == 0 means that it is empty 71 * Start with an Empty OEvent. UID == 0 means that it is empty
63 */ 72 */
64 OEvent(int uid = 0); 73 OEvent(int uid = 0);
65 74
66 /** 75 /**
67 * copy c'tor 76 * copy c'tor
68 */ 77 */
69 OEvent( const OEvent& ); 78 OEvent( const OEvent& );
70 ~OEvent(); 79 ~OEvent();
71 OEvent &operator=( const OEvent& ); 80 OEvent &operator=( const OEvent& );
72 81
73 QString description()const; 82 QString description()const;
74 void setDescription( const QString& description ); 83 void setDescription( const QString& description );
75 84
76 QString location()const; 85 QString location()const;
77 void setLocation( const QString& loc ); 86 void setLocation( const QString& loc );
78 87
79 bool hasNotifiers()const; 88 bool hasNotifiers()const;
80 OPimNotifyManager &notifiers()const; 89 OPimNotifyManager &notifiers()const;
81 90
82 ORecur recurrence()const; 91 ORecur recurrence()const;
83 void setRecurrence( const ORecur& ); 92 void setRecurrence( const ORecur& );
84 bool hasRecurrence()const; 93 bool hasRecurrence()const;
85 94
86 QString note()const; 95 QString note()const;
87 void setNote( const QString& note ); 96 void setNote( const QString& note );
88 97
89 98
90 QDateTime createdDateTime()const; 99 QDateTime createdDateTime()const;
91 void setCreatedDateTime( const QDateTime& dt); 100 void setCreatedDateTime( const QDateTime& dt);
92 101
93 /** set the date to dt. dt is the QDateTime in localtime */ 102 /** set the date to dt. dt is the QDateTime in localtime */
94 void setStartDateTime( const QDateTime& ); 103 void setStartDateTime( const QDateTime& );
95 /** returns the datetime in the local timeZone */ 104 /** returns the datetime in the local timeZone */
96 QDateTime startDateTime()const; 105 QDateTime startDateTime()const;
97 106
98 /** returns the start datetime in the current zone */ 107 /** returns the start datetime in the current zone */
99 QDateTime startDateTimeInZone()const; 108 QDateTime startDateTimeInZone()const;
100 109
101 /** in current timezone */ 110 /** in current timezone */
102 void setEndDateTime( const QDateTime& ); 111 void setEndDateTime( const QDateTime& );
103 /** in current timezone */ 112 /** in current timezone */
104 QDateTime endDateTime()const; 113 QDateTime endDateTime()const;
105 QDateTime endDateTimeInZone()const; 114 QDateTime endDateTimeInZone()const;
106 115
107 bool isMultipleDay()const; 116 bool isMultipleDay()const;
108 bool isAllDay()const; 117 bool isAllDay()const;
109 void setAllDay( bool isAllDay ); 118 void setAllDay( bool isAllDay );
110 119
111 /* pin this event to a timezone! FIXME */ 120 /* pin this event to a timezone! FIXME */
112 void setTimeZone( const QString& timeZone ); 121 void setTimeZone( const QString& timeZone );
113 QString timeZone()const; 122 QString timeZone()const;
114 123
115 124
116 virtual bool match( const QRegExp& )const; 125 virtual bool match( const QRegExp& )const;
117 126
118 /** For exception to recurrence here is a list of children... */ 127 /** For exception to recurrence here is a list of children... */
119 QArray<int> children()const; 128 QArray<int> children()const;
120 void setChildren( const QArray<int>& ); 129 void setChildren( const QArray<int>& );
121 void addChild( int uid ); 130 void addChild( int uid );
122 void removeChild( int uid ); 131 void removeChild( int uid );
123 132
124 /** return the parent OEvent */ 133 /** return the parent OEvent */
125 int parent()const; 134 int parent()const;
126 void setParent( int uid ); 135 void setParent( int uid );
127 136
128 137
129 /* needed reimp */ 138 /* needed reimp */
130 QString toRichText()const; 139 QString toRichText()const;
131 QString toShortText()const; 140 QString toShortText()const;
132 QString type()const; 141 QString type()const;
133 142
134 QMap<int, QString> toMap()const; 143 QMap<int, QString> toMap()const;
144 void fromMap( const QMap<int, QString>& map );
135 QString recordField(int )const; 145 QString recordField(int )const;
136 146
137 static int rtti(); 147 static int rtti();
138 148
139 bool loadFromStream( QDataStream& ); 149 bool loadFromStream( QDataStream& );
140 bool saveToStream( QDataStream& )const; 150 bool saveToStream( QDataStream& )const;
141 151
142/* bool operator==( const OEvent& ); 152/* bool operator==( const OEvent& );
143 bool operator!=( const OEvent& ); 153 bool operator!=( const OEvent& );
144 bool operator<( const OEvent& ); 154 bool operator<( const OEvent& );
145 bool operator<=( const OEvent& ); 155 bool operator<=( const OEvent& );
146 bool operator>( const OEvent& ); 156 bool operator>( const OEvent& );
147 bool operator>=(const OEvent& ); 157 bool operator>=(const OEvent& );
148*/ 158*/
149private: 159private:
150 inline void changeOrModify(); 160 inline void changeOrModify();
151 void deref(); 161 void deref();
152 struct Data; 162 struct Data;
153 Data* data; 163 Data* data;
154 class Private; 164 class Private;
155 Private* priv; 165 Private* priv;
156 166
157}; 167};
158 168
159/** 169/**
160 * AN Event can span through multiple days. We split up a multiday eve 170 * AN Event can span through multiple days. We split up a multiday eve
161 */ 171 */
162class OEffectiveEvent { 172class OEffectiveEvent {
163public: 173public:
164 typedef QValueList<OEffectiveEvent> ValueList; 174 typedef QValueList<OEffectiveEvent> ValueList;
165 enum Position { MidWay, Start, End, StartEnd }; 175 enum Position { MidWay, Start, End, StartEnd };
166 // If we calculate the effective event of a multi-day event 176 // If we calculate the effective event of a multi-day event
167 // we have to figure out whether we are at the first day, 177 // we have to figure out whether we are at the first day,
168 // at the end, or anywhere else ("middle"). This is important 178 // at the end, or anywhere else ("middle"). This is important
169 // for the start/end times (00:00/23:59) 179 // for the start/end times (00:00/23:59)
170 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi- 180 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi-
171 // day event 181 // day event
172 // Start: start time -> 23:59 182 // Start: start time -> 23:59
173 // End: 00:00 -> end time 183 // End: 00:00 -> end time
174 // Start | End == StartEnd: for single-day events (default) 184 // Start | End == StartEnd: for single-day events (default)
175 // here we draw start time -> end time 185 // here we draw start time -> end time
176 OEffectiveEvent(); 186 OEffectiveEvent();
177 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd ); 187 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd );
178 OEffectiveEvent( const OEffectiveEvent& ); 188 OEffectiveEvent( const OEffectiveEvent& );
179 OEffectiveEvent &operator=(const OEffectiveEvent& ); 189 OEffectiveEvent &operator=(const OEffectiveEvent& );
180 ~OEffectiveEvent(); 190 ~OEffectiveEvent();
181 191
182 void setStartTime( const QTime& ); 192 void setStartTime( const QTime& );
183 void setEndTime( const QTime& ); 193 void setEndTime( const QTime& );
184 void setEvent( const OEvent& ); 194 void setEvent( const OEvent& );
185 void setDate( const QDate& ); 195 void setDate( const QDate& );
186 196
187 void setEffectiveDates( const QDate& from, const QDate& to ); 197 void setEffectiveDates( const QDate& from, const QDate& to );
188 198
189 QString description()const; 199 QString description()const;
190 QString location()const; 200 QString location()const;
191 QString note()const; 201 QString note()const;
192 OEvent event()const; 202 OEvent event()const;
193 QTime startTime()const; 203 QTime startTime()const;
194 QTime endTime()const; 204 QTime endTime()const;
195 QDate date()const; 205 QDate date()const;
196 206
197 /* return the length in hours */ 207 /* return the length in hours */
198 int length()const; 208 int length()const;
199 int size()const; 209 int size()const;
200 210
201 QDate startDate()const; 211 QDate startDate()const;
202 QDate endDate()const; 212 QDate endDate()const;
203 213
204 bool operator<( const OEffectiveEvent &e ) const; 214 bool operator<( const OEffectiveEvent &e ) const;
205 bool operator<=( const OEffectiveEvent &e ) const; 215 bool operator<=( const OEffectiveEvent &e ) const;
206 bool operator==( const OEffectiveEvent &e ) const; 216 bool operator==( const OEffectiveEvent &e ) const;
207 bool operator!=( const OEffectiveEvent &e ) const; 217 bool operator!=( const OEffectiveEvent &e ) const;
208 bool operator>( const OEffectiveEvent &e ) const; 218 bool operator>( const OEffectiveEvent &e ) const;
209 bool operator>= ( const OEffectiveEvent &e ) const; 219 bool operator>= ( const OEffectiveEvent &e ) const;
210 220
211private: 221private:
212 void deref(); 222 void deref();
213 inline void changeOrModify(); 223 inline void changeOrModify();
214 class Private; 224 class Private;
215 Private* priv; 225 Private* priv;
216 struct Data; 226 struct Data;
217 Data* data; 227 Data* data;
218 228
219}; 229};
220#endif 230#endif
diff --git a/libopie/pim/orecur.cpp b/libopie/pim/orecur.cpp
index 8c9ad46..f46f22e 100644
--- a/libopie/pim/orecur.cpp
+++ b/libopie/pim/orecur.cpp
@@ -1,292 +1,300 @@
1#include <time.h> 1#include <time.h>
2 2
3#include <qshared.h> 3#include <qshared.h>
4 4
5#include <qtopia/timeconversion.h> 5#include <qtopia/timeconversion.h>
6 6
7#include "otimezone.h" 7#include "otimezone.h"
8#include "orecur.h" 8#include "orecur.h"
9 9
10struct ORecur::Data : public QShared { 10struct ORecur::Data : public QShared {
11 Data() : QShared() { 11 Data() : QShared() {
12 type = ORecur::NoRepeat; 12 type = ORecur::NoRepeat;
13 freq = -1; 13 freq = -1;
14 days = 0; 14 days = 0;
15 pos = 0; 15 pos = 0;
16 create = QDateTime::currentDateTime(); 16 create = QDateTime::currentDateTime();
17 hasEnd = FALSE; 17 hasEnd = FALSE;
18 end = QDate::currentDate(); 18 end = QDate::currentDate();
19 } 19 }
20 char days; // Q_UINT8 for 8 seven days;) 20 char days; // Q_UINT8 for 8 seven days;)
21 ORecur::RepeatType type; 21 ORecur::RepeatType type;
22 int freq; 22 int freq;
23 int pos; 23 int pos;
24 bool hasEnd : 1; 24 bool hasEnd : 1;
25 QDate end; 25 QDate end;
26 QDateTime create; 26 QDateTime create;
27 int rep; 27 int rep;
28 QString app; 28 QString app;
29 ExceptionList list; 29 ExceptionList list;
30 QDate start; 30 QDate start;
31}; 31};
32 32
33 33
34ORecur::ORecur() { 34ORecur::ORecur() {
35 data = new Data; 35 data = new Data;
36} 36}
37
38ORecur::ORecur( const QMap<int, QString>& map )
39{
40 ORecur();
41 fromMap( map );
42}
43
44
37ORecur::ORecur( const ORecur& rec) 45ORecur::ORecur( const ORecur& rec)
38 : data( rec.data ) 46 : data( rec.data )
39{ 47{
40 data->ref(); 48 data->ref();
41} 49}
42ORecur::~ORecur() { 50ORecur::~ORecur() {
43 if ( data->deref() ) { 51 if ( data->deref() ) {
44 delete data; 52 delete data;
45 data = 0l; 53 data = 0l;
46 } 54 }
47} 55}
48void ORecur::deref() { 56void ORecur::deref() {
49 if ( data->deref() ) { 57 if ( data->deref() ) {
50 delete data; 58 delete data;
51 data = 0l; 59 data = 0l;
52 } 60 }
53} 61}
54bool ORecur::operator==( const ORecur& )const { 62bool ORecur::operator==( const ORecur& )const {
55 return false; 63 return false;
56} 64}
57ORecur &ORecur::operator=( const ORecur& re) { 65ORecur &ORecur::operator=( const ORecur& re) {
58 if ( *this == re ) return *this; 66 if ( *this == re ) return *this;
59 67
60 re.data->ref(); 68 re.data->ref();
61 deref(); 69 deref();
62 data = re.data; 70 data = re.data;
63 71
64 return *this; 72 return *this;
65} 73}
66bool ORecur::doesRecur()const { 74bool ORecur::doesRecur()const {
67 return !( type() == NoRepeat ); 75 return !( type() == NoRepeat );
68} 76}
69/* 77/*
70 * we try to be smart here 78 * we try to be smart here
71 * 79 *
72 */ 80 */
73bool ORecur::doesRecur( const QDate& date ) { 81bool ORecur::doesRecur( const QDate& date ) {
74 /* the day before the recurrance */ 82 /* the day before the recurrance */
75 QDate da = date.addDays(-1); 83 QDate da = date.addDays(-1);
76 84
77 QDate recur; 85 QDate recur;
78 if (!nextOcurrence( da, recur ) ) 86 if (!nextOcurrence( da, recur ) )
79 return false; 87 return false;
80 88
81 return (recur == date); 89 return (recur == date);
82} 90}
83// FIXME unuglify! 91// FIXME unuglify!
84// GPL from Datebookdb.cpp 92// GPL from Datebookdb.cpp
85// FIXME exception list! 93// FIXME exception list!
86bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { 94bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
87 bool stillLooking; 95 bool stillLooking;
88 stillLooking = p_nextOccurrence( from, next ); 96 stillLooking = p_nextOccurrence( from, next );
89 while ( stillLooking && data->list.contains(next) ) 97 while ( stillLooking && data->list.contains(next) )
90 stillLooking = p_nextOccurrence( next.addDays(1), next ); 98 stillLooking = p_nextOccurrence( next.addDays(1), next );
91 99
92 return stillLooking; 100 return stillLooking;
93} 101}
94bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) { 102bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) {
95 103
96 // easy checks, first are we too far in the future or too far in the past? 104 // easy checks, first are we too far in the future or too far in the past?
97 QDate tmpDate; 105 QDate tmpDate;
98 int freq = frequency(); 106 int freq = frequency();
99 int diff, diff2, a; 107 int diff, diff2, a;
100 int iday, imonth, iyear; 108 int iday, imonth, iyear;
101 int dayOfWeek = 0; 109 int dayOfWeek = 0;
102 int firstOfWeek = 0; 110 int firstOfWeek = 0;
103 int weekOfMonth; 111 int weekOfMonth;
104 112
105 113
106 if (hasEndDate() && endDate() < from) 114 if (hasEndDate() && endDate() < from)
107 return FALSE; 115 return FALSE;
108 116
109 if (start() >= from ) { 117 if (start() >= from ) {
110 next = start(); 118 next = start();
111 return TRUE; 119 return TRUE;
112 } 120 }
113 121
114 switch ( type() ) { 122 switch ( type() ) {
115 case Weekly: 123 case Weekly:
116 /* weekly is just daily by 7 */ 124 /* weekly is just daily by 7 */
117 /* first convert the repeatPattern.Days() mask to the next 125 /* first convert the repeatPattern.Days() mask to the next
118 day of week valid after from */ 126 day of week valid after from */
119 dayOfWeek = from.dayOfWeek(); 127 dayOfWeek = from.dayOfWeek();
120 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */ 128 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */
121 129
122 /* this is done in case freq > 1 and from in week not 130 /* this is done in case freq > 1 and from in week not
123 for this round */ 131 for this round */
124 // firstOfWeek = 0; this is already done at decl. 132 // firstOfWeek = 0; this is already done at decl.
125 while(!((1 << firstOfWeek) & days() )) 133 while(!((1 << firstOfWeek) & days() ))
126 firstOfWeek++; 134 firstOfWeek++;
127 135
128 /* there is at least one 'day', or there would be no event */ 136 /* there is at least one 'day', or there would be no event */
129 while(!((1 << (dayOfWeek % 7)) & days() )) 137 while(!((1 << (dayOfWeek % 7)) & days() ))
130 dayOfWeek++; 138 dayOfWeek++;
131 139
132 dayOfWeek = dayOfWeek % 7; /* the actual day of week */ 140 dayOfWeek = dayOfWeek % 7; /* the actual day of week */
133 dayOfWeek -= start().dayOfWeek() -1; 141 dayOfWeek -= start().dayOfWeek() -1;
134 142
135 firstOfWeek = firstOfWeek % 7; /* the actual first of week */ 143 firstOfWeek = firstOfWeek % 7; /* the actual first of week */
136 firstOfWeek -= start().dayOfWeek() -1; 144 firstOfWeek -= start().dayOfWeek() -1;
137 145
138 // dayOfWeek may be negitive now 146 // dayOfWeek may be negitive now
139 // day of week is number of days to add to start day 147 // day of week is number of days to add to start day
140 148
141 freq *= 7; 149 freq *= 7;
142 // FALL-THROUGH !!!!! 150 // FALL-THROUGH !!!!!
143 case Daily: 151 case Daily:
144 // the add is for the possible fall through from weekly */ 152 // the add is for the possible fall through from weekly */
145 if(start().addDays(dayOfWeek) > from) { 153 if(start().addDays(dayOfWeek) > from) {
146 /* first week exception */ 154 /* first week exception */
147 next = QDate(start().addDays(dayOfWeek) ); 155 next = QDate(start().addDays(dayOfWeek) );
148 if ((next > endDate()) 156 if ((next > endDate())
149 && hasEndDate() ) 157 && hasEndDate() )
150 return FALSE; 158 return FALSE;
151 return TRUE; 159 return TRUE;
152 } 160 }
153 /* if from is middle of a non-week */ 161 /* if from is middle of a non-week */
154 162
155 diff = start().addDays(dayOfWeek).daysTo(from) % freq; 163 diff = start().addDays(dayOfWeek).daysTo(from) % freq;
156 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq; 164 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
157 165
158 if(diff != 0) 166 if(diff != 0)
159 diff = freq - diff; 167 diff = freq - diff;
160 if(diff2 != 0) 168 if(diff2 != 0)
161 diff2 = freq - diff2; 169 diff2 = freq - diff2;
162 diff = QMIN(diff, diff2); 170 diff = QMIN(diff, diff2);
163 171
164 next = QDate(from.addDays(diff)); 172 next = QDate(from.addDays(diff));
165 if ( (next > endDate()) 173 if ( (next > endDate())
166 && hasEndDate() ) 174 && hasEndDate() )
167 return FALSE; 175 return FALSE;
168 return TRUE; 176 return TRUE;
169 case MonthlyDay: 177 case MonthlyDay:
170 iday = from.day(); 178 iday = from.day();
171 iyear = from.year(); 179 iyear = from.year();
172 imonth = from.month(); 180 imonth = from.month();
173 /* find equivelent day of month for this month */ 181 /* find equivelent day of month for this month */
174 dayOfWeek = start().dayOfWeek(); 182 dayOfWeek = start().dayOfWeek();
175 weekOfMonth = (start().day() - 1) / 7; 183 weekOfMonth = (start().day() - 1) / 7;
176 184
177 /* work out when the next valid month is */ 185 /* work out when the next valid month is */
178 a = from.year() - start().year(); 186 a = from.year() - start().year();
179 a *= 12; 187 a *= 12;
180 a = a + (imonth - start().month()); 188 a = a + (imonth - start().month());
181 /* a is e.start()monthsFrom(from); */ 189 /* a is e.start()monthsFrom(from); */
182 if(a % freq) { 190 if(a % freq) {
183 a = freq - (a % freq); 191 a = freq - (a % freq);
184 imonth = from.month() + a; 192 imonth = from.month() + a;
185 if (imonth > 12) { 193 if (imonth > 12) {
186 imonth--; 194 imonth--;
187 iyear += imonth / 12; 195 iyear += imonth / 12;
188 imonth = imonth % 12; 196 imonth = imonth % 12;
189 imonth++; 197 imonth++;
190 } 198 }
191 } 199 }
192 /* imonth is now the first month after or on 200 /* imonth is now the first month after or on
193 from that matches the frequency given */ 201 from that matches the frequency given */
194 202
195 /* find for this month */ 203 /* find for this month */
196 tmpDate = QDate( iyear, imonth, 1 ); 204 tmpDate = QDate( iyear, imonth, 1 );
197 205
198 iday = 1; 206 iday = 1;
199 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 207 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
200 iday += 7 * weekOfMonth; 208 iday += 7 * weekOfMonth;
201 while (iday > tmpDate.daysInMonth()) { 209 while (iday > tmpDate.daysInMonth()) {
202 imonth += freq; 210 imonth += freq;
203 if (imonth > 12) { 211 if (imonth > 12) {
204 imonth--; 212 imonth--;
205 iyear += imonth / 12; 213 iyear += imonth / 12;
206 imonth = imonth % 12; 214 imonth = imonth % 12;
207 imonth++; 215 imonth++;
208 } 216 }
209 tmpDate = QDate( iyear, imonth, 1 ); 217 tmpDate = QDate( iyear, imonth, 1 );
210 /* these loops could go for a while, check end case now */ 218 /* these loops could go for a while, check end case now */
211 if ((tmpDate > endDate()) && hasEndDate() ) 219 if ((tmpDate > endDate()) && hasEndDate() )
212 return FALSE; 220 return FALSE;
213 iday = 1; 221 iday = 1;
214 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 222 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
215 iday += 7 * weekOfMonth; 223 iday += 7 * weekOfMonth;
216 } 224 }
217 tmpDate = QDate(iyear, imonth, iday); 225 tmpDate = QDate(iyear, imonth, iday);
218 226
219 if (tmpDate >= from) { 227 if (tmpDate >= from) {
220 next = tmpDate; 228 next = tmpDate;
221 if ((next > endDate() ) && hasEndDate() ) 229 if ((next > endDate() ) && hasEndDate() )
222 return FALSE; 230 return FALSE;
223 return TRUE; 231 return TRUE;
224 } 232 }
225 233
226 /* need to find the next iteration */ 234 /* need to find the next iteration */
227 do { 235 do {
228 imonth += freq; 236 imonth += freq;
229 if (imonth > 12) { 237 if (imonth > 12) {
230 imonth--; 238 imonth--;
231 iyear += imonth / 12; 239 iyear += imonth / 12;
232 imonth = imonth % 12; 240 imonth = imonth % 12;
233 imonth++; 241 imonth++;
234 } 242 }
235 tmpDate = QDate( iyear, imonth, 1 ); 243 tmpDate = QDate( iyear, imonth, 1 );
236 /* these loops could go for a while, check end case now */ 244 /* these loops could go for a while, check end case now */
237 if ((tmpDate > endDate()) && hasEndDate() ) 245 if ((tmpDate > endDate()) && hasEndDate() )
238 return FALSE; 246 return FALSE;
239 iday = 1; 247 iday = 1;
240 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 248 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
241 iday += 7 * weekOfMonth; 249 iday += 7 * weekOfMonth;
242 } while (iday > tmpDate.daysInMonth()); 250 } while (iday > tmpDate.daysInMonth());
243 tmpDate = QDate(iyear, imonth, iday); 251 tmpDate = QDate(iyear, imonth, iday);
244 252
245 next = tmpDate; 253 next = tmpDate;
246 if ((next > endDate()) && hasEndDate() ) 254 if ((next > endDate()) && hasEndDate() )
247 return FALSE; 255 return FALSE;
248 return TRUE; 256 return TRUE;
249 case MonthlyDate: 257 case MonthlyDate:
250 iday = start().day(); 258 iday = start().day();
251 iyear = from.year(); 259 iyear = from.year();
252 imonth = from.month(); 260 imonth = from.month();
253 261
254 a = from.year() - start().year(); 262 a = from.year() - start().year();
255 a *= 12; 263 a *= 12;
256 a = a + (imonth - start().month()); 264 a = a + (imonth - start().month());
257 /* a is e.start()monthsFrom(from); */ 265 /* a is e.start()monthsFrom(from); */
258 if(a % freq) { 266 if(a % freq) {
259 a = freq - (a % freq); 267 a = freq - (a % freq);
260 imonth = from.month() + a; 268 imonth = from.month() + a;
261 if (imonth > 12) { 269 if (imonth > 12) {
262 imonth--; 270 imonth--;
263 iyear += imonth / 12; 271 iyear += imonth / 12;
264 imonth = imonth % 12; 272 imonth = imonth % 12;
265 imonth++; 273 imonth++;
266 } 274 }
267 } 275 }
268 /* imonth is now the first month after or on 276 /* imonth is now the first month after or on
269 from that matches the frequencey given */ 277 from that matches the frequencey given */
270 278
271 /* this could go for a while, worse case, 4*12 iterations, probably */ 279 /* this could go for a while, worse case, 4*12 iterations, probably */
272 while(!QDate::isValid(iyear, imonth, iday) ) { 280 while(!QDate::isValid(iyear, imonth, iday) ) {
273 imonth += freq; 281 imonth += freq;
274 if (imonth > 12) { 282 if (imonth > 12) {
275 imonth--; 283 imonth--;
276 iyear += imonth / 12; 284 iyear += imonth / 12;
277 imonth = imonth % 12; 285 imonth = imonth % 12;
278 imonth++; 286 imonth++;
279 } 287 }
280 /* these loops could go for a while, check end case now */ 288 /* these loops could go for a while, check end case now */
281 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 289 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
282 return FALSE; 290 return FALSE;
283 } 291 }
284 292
285 if(QDate(iyear, imonth, iday) >= from) { 293 if(QDate(iyear, imonth, iday) >= from) {
286 /* done */ 294 /* done */
287 next = QDate(iyear, imonth, iday); 295 next = QDate(iyear, imonth, iday);
288 if ((next > endDate()) && hasEndDate() ) 296 if ((next > endDate()) && hasEndDate() )
289 return FALSE; 297 return FALSE;
290 return TRUE; 298 return TRUE;
291 } 299 }
292 300
diff --git a/libopie/pim/orecur.h b/libopie/pim/orecur.h
index 47901b0..7750c12 100644
--- a/libopie/pim/orecur.h
+++ b/libopie/pim/orecur.h
@@ -1,101 +1,102 @@
1/* 1/*
2 * GPL from TT 2 * GPL from TT
3 */ 3 */
4 4
5#ifndef OPIE_RECUR_H 5#ifndef OPIE_RECUR_H
6#define OPIE_RECUR_H 6#define OPIE_RECUR_H
7 7
8#include <sys/types.h> 8#include <sys/types.h>
9 9
10#include <qdatetime.h> 10#include <qdatetime.h>
11#include <qvaluelist.h> 11#include <qvaluelist.h>
12#include <qmap.h> 12#include <qmap.h>
13 13
14class ORecur { 14class ORecur {
15public: 15public:
16 typedef QValueList<QDate> ExceptionList; 16 typedef QValueList<QDate> ExceptionList;
17 enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay, 17 enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay,
18 MonthlyDate, Yearly }; 18 MonthlyDate, Yearly };
19 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08, 19 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08,
20 FRI = 0x10, SAT = 0x20, SUN = 0x40 }; 20 FRI = 0x10, SAT = 0x20, SUN = 0x40 };
21 enum Fields{ RType = 0, RWeekdays, RPosition, RFreq, RHasEndDate, 21 enum Fields{ RType = 0, RWeekdays, RPosition, RFreq, RHasEndDate,
22 EndDate, Created, Exceptions }; 22 EndDate, Created, Exceptions };
23 23
24 ORecur(); 24 ORecur();
25 ORecur( const QMap<int, QString>& map );
25 ORecur( const ORecur& ); 26 ORecur( const ORecur& );
26 ~ORecur(); 27 ~ORecur();
27 28
28 ORecur &operator=( const ORecur& ); 29 ORecur &operator=( const ORecur& );
29 bool operator==(const ORecur& )const; 30 bool operator==(const ORecur& )const;
30 31
31 bool doesRecur()const; 32 bool doesRecur()const;
32 /* if it recurrs on that day */ 33 /* if it recurrs on that day */
33 bool doesRecur( const QDate& ); 34 bool doesRecur( const QDate& );
34 RepeatType type()const; 35 RepeatType type()const;
35 int frequency()const; 36 int frequency()const;
36 int position()const; 37 int position()const;
37 char days()const; 38 char days()const;
38 bool hasEndDate()const; 39 bool hasEndDate()const;
39 QDate start()const; 40 QDate start()const;
40 QDate endDate()const; 41 QDate endDate()const;
41 QDateTime createdDateTime()const; 42 QDateTime createdDateTime()const;
42 /** 43 /**
43 * starting on monday=0, sunday=6 44 * starting on monday=0, sunday=6
44 * for convience 45 * for convience
45 */ 46 */
46 bool repeatOnWeekDay( int day )const; 47 bool repeatOnWeekDay( int day )const;
47 48
48 /** 49 /**
49 * FromWhereToStart is not included!!! 50 * FromWhereToStart is not included!!!
50 */ 51 */
51 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate ); 52 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate );
52 53
53 /** 54 /**
54 * The module this ORecur belongs to 55 * The module this ORecur belongs to
55 */ 56 */
56 QString service()const; 57 QString service()const;
57 58
58 /* 59 /*
59 * reference to the exception list 60 * reference to the exception list
60 */ 61 */
61 ExceptionList &exceptions(); 62 ExceptionList &exceptions();
62 63
63 /** 64 /**
64 * the current repetition 65 * the current repetition
65 */ 66 */
66 int repetition()const; 67 int repetition()const;
67 68
68 void setType( const RepeatType& ); 69 void setType( const RepeatType& );
69 void setFrequency( int freq ); 70 void setFrequency( int freq );
70 void setPosition( int pos ); 71 void setPosition( int pos );
71 void setDays( char c); 72 void setDays( char c);
72 void setEndDate( const QDate& dt ); 73 void setEndDate( const QDate& dt );
73 void setStart( const QDate& dt ); 74 void setStart( const QDate& dt );
74 void setCreatedDateTime( const QDateTime& ); 75 void setCreatedDateTime( const QDateTime& );
75 void setHasEndDate( bool b ); 76 void setHasEndDate( bool b );
76 void setRepitition(int ); 77 void setRepitition(int );
77 78
78 void setService( const QString& ser ); 79 void setService( const QString& ser );
79 80
80 QMap<int, QString> toMap() const; 81 QMap<int, QString> toMap() const;
81 void fromMap( const QMap<int, QString>& map ); 82 void fromMap( const QMap<int, QString>& map );
82 83
83 /* almost internal */ 84 /* almost internal */
84 QString toString()const; 85 QString toString()const;
85private: 86private:
86 bool p_nextOccurrence( const QDate& from, QDate& next ); 87 bool p_nextOccurrence( const QDate& from, QDate& next );
87 void deref(); 88 void deref();
88 inline void checkOrModify(); 89 inline void checkOrModify();
89 90
90 /* Converts rType to String */ 91 /* Converts rType to String */
91 QString rTypeString() const; 92 QString rTypeString() const;
92 /* Returns a map to convert Stringname for RType to RepeatType */ 93 /* Returns a map to convert Stringname for RType to RepeatType */
93 QMap<QString, RepeatType> rTypeValueConvertMap() const; 94 QMap<QString, RepeatType> rTypeValueConvertMap() const;
94 95
95 class Data; 96 class Data;
96 Data* data; 97 Data* data;
97 class ORecurPrivate; 98 class ORecurPrivate;
98 ORecurPrivate *d; 99 ORecurPrivate *d;
99}; 100};
100 101
101#endif 102#endif
diff --git a/libopie/pim/otodoaccesssql.cpp b/libopie/pim/otodoaccesssql.cpp
index 3913661..75a0860 100644
--- a/libopie/pim/otodoaccesssql.cpp
+++ b/libopie/pim/otodoaccesssql.cpp
@@ -46,525 +46,528 @@ namespace {
46 /** 46 /**
47 * inserts/adds a OTodo to the table 47 * inserts/adds a OTodo to the table
48 */ 48 */
49 class InsertQuery : public OSQLQuery { 49 class InsertQuery : public OSQLQuery {
50 public: 50 public:
51 InsertQuery(const OTodo& ); 51 InsertQuery(const OTodo& );
52 ~InsertQuery(); 52 ~InsertQuery();
53 QString query()const; 53 QString query()const;
54 private: 54 private:
55 OTodo m_todo; 55 OTodo m_todo;
56 }; 56 };
57 57
58 /** 58 /**
59 * removes one from the table 59 * removes one from the table
60 */ 60 */
61 class RemoveQuery : public OSQLQuery { 61 class RemoveQuery : public OSQLQuery {
62 public: 62 public:
63 RemoveQuery(int uid ); 63 RemoveQuery(int uid );
64 ~RemoveQuery(); 64 ~RemoveQuery();
65 QString query()const; 65 QString query()const;
66 private: 66 private:
67 int m_uid; 67 int m_uid;
68 }; 68 };
69 69
70 /** 70 /**
71 * Clears (delete) a Table 71 * Clears (delete) a Table
72 */ 72 */
73 class ClearQuery : public OSQLQuery { 73 class ClearQuery : public OSQLQuery {
74 public: 74 public:
75 ClearQuery(); 75 ClearQuery();
76 ~ClearQuery(); 76 ~ClearQuery();
77 QString query()const; 77 QString query()const;
78 78
79 }; 79 };
80 80
81 /** 81 /**
82 * a find query 82 * a find query
83 */ 83 */
84 class FindQuery : public OSQLQuery { 84 class FindQuery : public OSQLQuery {
85 public: 85 public:
86 FindQuery(int uid); 86 FindQuery(int uid);
87 FindQuery(const QArray<int>& ); 87 FindQuery(const QArray<int>& );
88 ~FindQuery(); 88 ~FindQuery();
89 QString query()const; 89 QString query()const;
90 private: 90 private:
91 QString single()const; 91 QString single()const;
92 QString multi()const; 92 QString multi()const;
93 QArray<int> m_uids; 93 QArray<int> m_uids;
94 int m_uid; 94 int m_uid;
95 }; 95 };
96 96
97 /** 97 /**
98 * overdue query 98 * overdue query
99 */ 99 */
100 class OverDueQuery : public OSQLQuery { 100 class OverDueQuery : public OSQLQuery {
101 public: 101 public:
102 OverDueQuery(); 102 OverDueQuery();
103 ~OverDueQuery(); 103 ~OverDueQuery();
104 QString query()const; 104 QString query()const;
105 }; 105 };
106 class EffQuery : public OSQLQuery { 106 class EffQuery : public OSQLQuery {
107 public: 107 public:
108 EffQuery( const QDate&, const QDate&, bool inc ); 108 EffQuery( const QDate&, const QDate&, bool inc );
109 ~EffQuery(); 109 ~EffQuery();
110 QString query()const; 110 QString query()const;
111 private: 111 private:
112 QString with()const; 112 QString with()const;
113 QString out()const; 113 QString out()const;
114 QDate m_start; 114 QDate m_start;
115 QDate m_end; 115 QDate m_end;
116 bool m_inc :1; 116 bool m_inc :1;
117 }; 117 };
118 118
119 119
120 CreateQuery::CreateQuery() : OSQLQuery() {} 120 CreateQuery::CreateQuery() : OSQLQuery() {}
121 CreateQuery::~CreateQuery() {} 121 CreateQuery::~CreateQuery() {}
122 QString CreateQuery::query()const { 122 QString CreateQuery::query()const {
123 QString qu; 123 QString qu;
124 qu += "create table todolist( uid PRIMARY KEY, categories, completed, "; 124 qu += "create table todolist( uid PRIMARY KEY, categories, completed, ";
125 qu += "description, summary, priority, DueDate, progress , state, "; 125 qu += "description, summary, priority, DueDate, progress , state, ";
126 // This is the recurrance-stuff .. Exceptions are currently not supported (see ORecur.cpp) ! (eilers) 126 // This is the recurrance-stuff .. Exceptions are currently not supported (see ORecur.cpp) ! (eilers)
127 qu += "RType, RWeekdays, RPosition, RFreq, RHasEndDate, EndDate, Created, Exceptions, "; 127 qu += "RType, RWeekdays, RPosition, RFreq, RHasEndDate, EndDate, Created, Exceptions, ";
128 qu += "reminders, alarms, maintainer, startdate, completeddate);"; 128 qu += "reminders, alarms, maintainer, startdate, completeddate);";
129 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );"; 129 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );";
130 return qu; 130 return qu;
131 } 131 }
132 132
133 LoadQuery::LoadQuery() : OSQLQuery() {} 133 LoadQuery::LoadQuery() : OSQLQuery() {}
134 LoadQuery::~LoadQuery() {} 134 LoadQuery::~LoadQuery() {}
135 QString LoadQuery::query()const { 135 QString LoadQuery::query()const {
136 QString qu; 136 QString qu;
137 // We do not need "distinct" here. The primary key is always unique.. 137 // We do not need "distinct" here. The primary key is always unique..
138 //qu += "select distinct uid from todolist"; 138 //qu += "select distinct uid from todolist";
139 qu += "select uid from todolist"; 139 qu += "select uid from todolist";
140 140
141 return qu; 141 return qu;
142 } 142 }
143 143
144 InsertQuery::InsertQuery( const OTodo& todo ) 144 InsertQuery::InsertQuery( const OTodo& todo )
145 : OSQLQuery(), m_todo( todo ) { 145 : OSQLQuery(), m_todo( todo ) {
146 } 146 }
147 InsertQuery::~InsertQuery() { 147 InsertQuery::~InsertQuery() {
148 } 148 }
149 /* 149 /*
150 * converts from a OTodo to a query 150 * converts from a OTodo to a query
151 * we leave out X-Ref + Alarms 151 * we leave out X-Ref + Alarms
152 */ 152 */
153 QString InsertQuery::query()const{ 153 QString InsertQuery::query()const{
154 154
155 int year, month, day; 155 int year, month, day;
156 year = month = day = 0; 156 year = month = day = 0;
157 if (m_todo.hasDueDate() ) { 157 if (m_todo.hasDueDate() ) {
158 QDate date = m_todo.dueDate(); 158 QDate date = m_todo.dueDate();
159 year = date.year(); 159 year = date.year();
160 month = date.month(); 160 month = date.month();
161 day = date.day(); 161 day = date.day();
162 } 162 }
163 int sYear = 0, sMonth = 0, sDay = 0; 163 int sYear = 0, sMonth = 0, sDay = 0;
164 if( m_todo.hasStartDate() ){ 164 if( m_todo.hasStartDate() ){
165 QDate sDate = m_todo.startDate(); 165 QDate sDate = m_todo.startDate();
166 sYear = sDate.year(); 166 sYear = sDate.year();
167 sMonth= sDate.month(); 167 sMonth= sDate.month();
168 sDay = sDate.day(); 168 sDay = sDate.day();
169 } 169 }
170 170
171 int eYear = 0, eMonth = 0, eDay = 0; 171 int eYear = 0, eMonth = 0, eDay = 0;
172 if( m_todo.hasCompletedDate() ){ 172 if( m_todo.hasCompletedDate() ){
173 QDate eDate = m_todo.completedDate(); 173 QDate eDate = m_todo.completedDate();
174 eYear = eDate.year(); 174 eYear = eDate.year();
175 eMonth= eDate.month(); 175 eMonth= eDate.month();
176 eDay = eDate.day(); 176 eDay = eDate.day();
177 } 177 }
178 QString qu; 178 QString qu;
179 QMap<int, QString> recMap = m_todo.recurrence().toMap(); 179 QMap<int, QString> recMap = m_todo.recurrence().toMap();
180 qu = "insert into todolist VALUES(" 180 qu = "insert into todolist VALUES("
181 + QString::number( m_todo.uid() ) + "," 181 + QString::number( m_todo.uid() ) + ","
182 + "'" + m_todo.idsToString( m_todo.categories() ) + "'" + "," 182 + "'" + m_todo.idsToString( m_todo.categories() ) + "'" + ","
183 + QString::number( m_todo.isCompleted() ) + "," 183 + QString::number( m_todo.isCompleted() ) + ","
184 + "'" + m_todo.description() + "'" + "," 184 + "'" + m_todo.description() + "'" + ","
185 + "'" + m_todo.summary() + "'" + "," 185 + "'" + m_todo.summary() + "'" + ","
186 + QString::number(m_todo.priority() ) + "," 186 + QString::number(m_todo.priority() ) + ","
187 + "'" + QString::number(year) + "-" 187 + "'" + QString::number(year) + "-"
188 + QString::number(month) 188 + QString::number(month)
189 + "-" + QString::number( day ) + "'" + "," 189 + "-" + QString::number( day ) + "'" + ","
190 + QString::number( m_todo.progress() ) + "," 190 + QString::number( m_todo.progress() ) + ","
191 + QString::number( m_todo.state().state() ) + "," 191 + QString::number( m_todo.state().state() ) + ","
192 + "'" + recMap[ ORecur::RType ] + "'" + "," 192 + "'" + recMap[ ORecur::RType ] + "'" + ","
193 + "'" + recMap[ ORecur::RWeekdays ] + "'" + "," 193 + "'" + recMap[ ORecur::RWeekdays ] + "'" + ","
194 + "'" + recMap[ ORecur::RPosition ] + "'" + "," 194 + "'" + recMap[ ORecur::RPosition ] + "'" + ","
195 + "'" + recMap[ ORecur::RFreq ] + "'" + "," 195 + "'" + recMap[ ORecur::RFreq ] + "'" + ","
196 + "'" + recMap[ ORecur::RHasEndDate ] + "'" + "," 196 + "'" + recMap[ ORecur::RHasEndDate ] + "'" + ","
197 + "'" + recMap[ ORecur::EndDate ] + "'" + "," 197 + "'" + recMap[ ORecur::EndDate ] + "'" + ","
198 + "'" + recMap[ ORecur::Created ] + "'" + "," 198 + "'" + recMap[ ORecur::Created ] + "'" + ","
199 + "'" + recMap[ ORecur::Exceptions ] + "'" + ","; 199 + "'" + recMap[ ORecur::Exceptions ] + "'" + ",";
200 200
201 if ( m_todo.hasNotifiers() ) { 201 if ( m_todo.hasNotifiers() ) {
202 OPimNotifyManager manager = m_todo.notifiers(); 202 OPimNotifyManager manager = m_todo.notifiers();
203 qu += "'" + manager.remindersToString() + "'" + "," 203 qu += "'" + manager.remindersToString() + "'" + ","
204 + "'" + manager.alarmsToString() + "'" + ","; 204 + "'" + manager.alarmsToString() + "'" + ",";
205 } 205 }
206 else{ 206 else{
207 qu += QString( "''" ) + "," 207 qu += QString( "''" ) + ","
208 + "''" + ","; 208 + "''" + ",";
209 } 209 }
210 210
211 qu += QString( "''" ) + QString( "," ) // Maintainers (cur. not supported !) 211 qu += QString( "''" ) + QString( "," ) // Maintainers (cur. not supported !)
212 + "'" + QString::number(sYear) + "-" 212 + "'" + QString::number(sYear) + "-"
213 + QString::number(sMonth) 213 + QString::number(sMonth)
214 + "-" + QString::number(sDay) + "'" + "," 214 + "-" + QString::number(sDay) + "'" + ","
215 + "'" + QString::number(eYear) + "-" 215 + "'" + QString::number(eYear) + "-"
216 + QString::number(eMonth) 216 + QString::number(eMonth)
217 + "-"+QString::number(eDay) + "'" 217 + "-"+QString::number(eDay) + "'"
218 + ")"; 218 + ")";
219 219
220 qWarning("add %s", qu.latin1() ); 220 qWarning("add %s", qu.latin1() );
221 return qu; 221 return qu;
222 } 222 }
223 223
224 RemoveQuery::RemoveQuery(int uid ) 224 RemoveQuery::RemoveQuery(int uid )
225 : OSQLQuery(), m_uid( uid ) {} 225 : OSQLQuery(), m_uid( uid ) {}
226 RemoveQuery::~RemoveQuery() {} 226 RemoveQuery::~RemoveQuery() {}
227 QString RemoveQuery::query()const { 227 QString RemoveQuery::query()const {
228 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid); 228 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid);
229 return qu; 229 return qu;
230 } 230 }
231 231
232 232
233 ClearQuery::ClearQuery() 233 ClearQuery::ClearQuery()
234 : OSQLQuery() {} 234 : OSQLQuery() {}
235 ClearQuery::~ClearQuery() {} 235 ClearQuery::~ClearQuery() {}
236 QString ClearQuery::query()const { 236 QString ClearQuery::query()const {
237 QString qu = "drop table todolist"; 237 QString qu = "drop table todolist";
238 return qu; 238 return qu;
239 } 239 }
240 FindQuery::FindQuery(int uid) 240 FindQuery::FindQuery(int uid)
241 : OSQLQuery(), m_uid(uid ) { 241 : OSQLQuery(), m_uid(uid ) {
242 } 242 }
243 FindQuery::FindQuery(const QArray<int>& ints) 243 FindQuery::FindQuery(const QArray<int>& ints)
244 : OSQLQuery(), m_uids(ints){ 244 : OSQLQuery(), m_uids(ints){
245 } 245 }
246 FindQuery::~FindQuery() { 246 FindQuery::~FindQuery() {
247 } 247 }
248 QString FindQuery::query()const{ 248 QString FindQuery::query()const{
249 if (m_uids.count() == 0 ) 249 if (m_uids.count() == 0 )
250 return single(); 250 return single();
251 else 251 else
252 return multi(); 252 return multi();
253 } 253 }
254 QString FindQuery::single()const{ 254 QString FindQuery::single()const{
255 QString qu = "select * from todolist where uid = " + QString::number(m_uid); 255 QString qu = "select * from todolist where uid = " + QString::number(m_uid);
256 return qu; 256 return qu;
257 } 257 }
258 QString FindQuery::multi()const { 258 QString FindQuery::multi()const {
259 QString qu = "select * from todolist where "; 259 QString qu = "select * from todolist where ";
260 for (uint i = 0; i < m_uids.count(); i++ ) { 260 for (uint i = 0; i < m_uids.count(); i++ ) {
261 qu += " UID = " + QString::number( m_uids[i] ) + " OR"; 261 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
262 } 262 }
263 qu.remove( qu.length()-2, 2 ); 263 qu.remove( qu.length()-2, 2 );
264 return qu; 264 return qu;
265 } 265 }
266 266
267 OverDueQuery::OverDueQuery(): OSQLQuery() {} 267 OverDueQuery::OverDueQuery(): OSQLQuery() {}
268 OverDueQuery::~OverDueQuery() {} 268 OverDueQuery::~OverDueQuery() {}
269 QString OverDueQuery::query()const { 269 QString OverDueQuery::query()const {
270 QDate date = QDate::currentDate(); 270 QDate date = QDate::currentDate();
271 QString str; 271 QString str;
272 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() ); 272 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() );
273 273
274 return str; 274 return str;
275 } 275 }
276 276
277 277
278 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc ) 278 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc )
279 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {} 279 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {}
280 EffQuery::~EffQuery() {} 280 EffQuery::~EffQuery() {}
281 QString EffQuery::query()const { 281 QString EffQuery::query()const {
282 return m_inc ? with() : out(); 282 return m_inc ? with() : out();
283 } 283 }
284 QString EffQuery::with()const { 284 QString EffQuery::with()const {
285 QString str; 285 QString str;
286 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ") 286 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ")
287 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() ) 287 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() )
288 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() ); 288 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() );
289 return str; 289 return str;
290 } 290 }
291 QString EffQuery::out()const { 291 QString EffQuery::out()const {
292 QString str; 292 QString str;
293 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'") 293 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'")
294 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() ) 294 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() )
295 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() ); 295 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() );
296 296
297 return str; 297 return str;
298 } 298 }
299}; 299};
300 300
301OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file ) 301OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file )
302 : OTodoAccessBackend(), m_dict(15), m_dirty(true) 302 : OTodoAccessBackend(), m_dict(15), m_driver(NULL), m_dirty(true)
303{ 303{
304 QString fi = file; 304 QString fi = file;
305 if ( fi.isEmpty() ) 305 if ( fi.isEmpty() )
306 fi = Global::applicationFileName( "todolist", "todolist.db" ); 306 fi = Global::applicationFileName( "todolist", "todolist.db" );
307 OSQLManager man; 307 OSQLManager man;
308 m_driver = man.standard(); 308 m_driver = man.standard();
309 m_driver->setUrl(fi); 309 m_driver->setUrl(fi);
310 // fillDict(); 310 // fillDict();
311} 311}
312 312
313OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){ 313OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){
314 if( m_driver )
315 delete m_driver;
314} 316}
317
315bool OTodoAccessBackendSQL::load(){ 318bool OTodoAccessBackendSQL::load(){
316 if (!m_driver->open() ) 319 if (!m_driver->open() )
317 return false; 320 return false;
318 321
319 CreateQuery creat; 322 CreateQuery creat;
320 OSQLResult res = m_driver->query(&creat ); 323 OSQLResult res = m_driver->query(&creat );
321 324
322 m_dirty = true; 325 m_dirty = true;
323 return true; 326 return true;
324} 327}
325bool OTodoAccessBackendSQL::reload(){ 328bool OTodoAccessBackendSQL::reload(){
326 return load(); 329 return load();
327} 330}
328 331
329bool OTodoAccessBackendSQL::save(){ 332bool OTodoAccessBackendSQL::save(){
330 return m_driver->close(); 333 return m_driver->close();
331} 334}
332QArray<int> OTodoAccessBackendSQL::allRecords()const { 335QArray<int> OTodoAccessBackendSQL::allRecords()const {
333 if (m_dirty ) 336 if (m_dirty )
334 update(); 337 update();
335 338
336 return m_uids; 339 return m_uids;
337} 340}
338QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){ 341QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){
339 QArray<int> ints(0); 342 QArray<int> ints(0);
340 return ints; 343 return ints;
341} 344}
342OTodo OTodoAccessBackendSQL::find(int uid ) const{ 345OTodo OTodoAccessBackendSQL::find(int uid ) const{
343 FindQuery query( uid ); 346 FindQuery query( uid );
344 return todo( m_driver->query(&query) ); 347 return todo( m_driver->query(&query) );
345 348
346} 349}
347OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints, 350OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints,
348 uint cur, Frontend::CacheDirection dir ) const{ 351 uint cur, Frontend::CacheDirection dir ) const{
349 uint CACHE = readAhead(); 352 uint CACHE = readAhead();
350 qWarning("searching for %d", uid ); 353 qWarning("searching for %d", uid );
351 QArray<int> search( CACHE ); 354 QArray<int> search( CACHE );
352 uint size =0; 355 uint size =0;
353 OTodo to; 356 OTodo to;
354 357
355 // we try to cache CACHE items 358 // we try to cache CACHE items
356 switch( dir ) { 359 switch( dir ) {
357 /* forward */ 360 /* forward */
358 case 0: // FIXME: Not a good style to use magic numbers here (eilers) 361 case 0: // FIXME: Not a good style to use magic numbers here (eilers)
359 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) { 362 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) {
360 qWarning("size %d %d", size, ints[i] ); 363 qWarning("size %d %d", size, ints[i] );
361 search[size] = ints[i]; 364 search[size] = ints[i];
362 size++; 365 size++;
363 } 366 }
364 break; 367 break;
365 /* reverse */ 368 /* reverse */
366 case 1: // FIXME: Not a good style to use magic numbers here (eilers) 369 case 1: // FIXME: Not a good style to use magic numbers here (eilers)
367 for (uint i = cur; i != 0 && size < CACHE; i-- ) { 370 for (uint i = cur; i != 0 && size < CACHE; i-- ) {
368 search[size] = ints[i]; 371 search[size] = ints[i];
369 size++; 372 size++;
370 } 373 }
371 break; 374 break;
372 } 375 }
373 search.resize( size ); 376 search.resize( size );
374 FindQuery query( search ); 377 FindQuery query( search );
375 OSQLResult res = m_driver->query( &query ); 378 OSQLResult res = m_driver->query( &query );
376 if ( res.state() != OSQLResult::Success ) 379 if ( res.state() != OSQLResult::Success )
377 return to; 380 return to;
378 381
379 return todo( res ); 382 return todo( res );
380} 383}
381void OTodoAccessBackendSQL::clear() { 384void OTodoAccessBackendSQL::clear() {
382 ClearQuery cle; 385 ClearQuery cle;
383 OSQLResult res = m_driver->query( &cle ); 386 OSQLResult res = m_driver->query( &cle );
384 CreateQuery qu; 387 CreateQuery qu;
385 res = m_driver->query(&qu); 388 res = m_driver->query(&qu);
386} 389}
387bool OTodoAccessBackendSQL::add( const OTodo& t) { 390bool OTodoAccessBackendSQL::add( const OTodo& t) {
388 InsertQuery ins( t ); 391 InsertQuery ins( t );
389 OSQLResult res = m_driver->query( &ins ); 392 OSQLResult res = m_driver->query( &ins );
390 393
391 if ( res.state() == OSQLResult::Failure ) 394 if ( res.state() == OSQLResult::Failure )
392 return false; 395 return false;
393 int c = m_uids.count(); 396 int c = m_uids.count();
394 m_uids.resize( c+1 ); 397 m_uids.resize( c+1 );
395 m_uids[c] = t.uid(); 398 m_uids[c] = t.uid();
396 399
397 return true; 400 return true;
398} 401}
399bool OTodoAccessBackendSQL::remove( int uid ) { 402bool OTodoAccessBackendSQL::remove( int uid ) {
400 RemoveQuery rem( uid ); 403 RemoveQuery rem( uid );
401 OSQLResult res = m_driver->query(&rem ); 404 OSQLResult res = m_driver->query(&rem );
402 405
403 if ( res.state() == OSQLResult::Failure ) 406 if ( res.state() == OSQLResult::Failure )
404 return false; 407 return false;
405 408
406 m_dirty = true; 409 m_dirty = true;
407 return true; 410 return true;
408} 411}
409/* 412/*
410 * FIXME better set query 413 * FIXME better set query
411 * but we need the cache for that 414 * but we need the cache for that
412 * now we remove 415 * now we remove
413 */ 416 */
414bool OTodoAccessBackendSQL::replace( const OTodo& t) { 417bool OTodoAccessBackendSQL::replace( const OTodo& t) {
415 remove( t.uid() ); 418 remove( t.uid() );
416 bool b= add(t); 419 bool b= add(t);
417 m_dirty = false; // we changed some stuff but the UID stayed the same 420 m_dirty = false; // we changed some stuff but the UID stayed the same
418 return b; 421 return b;
419} 422}
420QArray<int> OTodoAccessBackendSQL::overDue() { 423QArray<int> OTodoAccessBackendSQL::overDue() {
421 OverDueQuery qu; 424 OverDueQuery qu;
422 return uids( m_driver->query(&qu ) ); 425 return uids( m_driver->query(&qu ) );
423} 426}
424QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s, 427QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s,
425 const QDate& t, 428 const QDate& t,
426 bool u) { 429 bool u) {
427 EffQuery ef(s, t, u ); 430 EffQuery ef(s, t, u );
428 return uids (m_driver->query(&ef) ); 431 return uids (m_driver->query(&ef) );
429} 432}
430/* 433/*
431 * 434 *
432 */ 435 */
433QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder, 436QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder,
434 int sortFilter, int cat ) { 437 int sortFilter, int cat ) {
435 qWarning("sorted %d, %d", asc, sortOrder ); 438 qWarning("sorted %d, %d", asc, sortOrder );
436 QString query; 439 QString query;
437 query = "select uid from todolist WHERE "; 440 query = "select uid from todolist WHERE ";
438 441
439 /* 442 /*
440 * Sort Filter stuff 443 * Sort Filter stuff
441 * not that straight forward 444 * not that straight forward
442 * FIXME: Replace magic numbers 445 * FIXME: Replace magic numbers
443 * 446 *
444 */ 447 */
445 /* Category */ 448 /* Category */
446 if ( sortFilter & 1 ) { 449 if ( sortFilter & 1 ) {
447 QString str; 450 QString str;
448 if (cat != 0 ) str = QString::number( cat ); 451 if (cat != 0 ) str = QString::number( cat );
449 query += " categories like '%" +str+"%' AND"; 452 query += " categories like '%" +str+"%' AND";
450 } 453 }
451 /* Show only overdue */ 454 /* Show only overdue */
452 if ( sortFilter & 2 ) { 455 if ( sortFilter & 2 ) {
453 QDate date = QDate::currentDate(); 456 QDate date = QDate::currentDate();
454 QString due; 457 QString due;
455 QString base; 458 QString base;
456 base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() ); 459 base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() );
457 query += " " + base + " AND"; 460 query += " " + base + " AND";
458 } 461 }
459 /* not show completed */ 462 /* not show completed */
460 if ( sortFilter & 4 ) { 463 if ( sortFilter & 4 ) {
461 query += " completed = 0 AND"; 464 query += " completed = 0 AND";
462 }else{ 465 }else{
463 query += " ( completed = 1 OR completed = 0) AND"; 466 query += " ( completed = 1 OR completed = 0) AND";
464 } 467 }
465 /* srtip the end */ 468 /* srtip the end */
466 query = query.remove( query.length()-3, 3 ); 469 query = query.remove( query.length()-3, 3 );
467 470
468 471
469 /* 472 /*
470 * sort order stuff 473 * sort order stuff
471 * quite straight forward 474 * quite straight forward
472 */ 475 */
473 query += "ORDER BY "; 476 query += "ORDER BY ";
474 switch( sortOrder ) { 477 switch( sortOrder ) {
475 /* completed */ 478 /* completed */
476 case 0: 479 case 0:
477 query += "completed"; 480 query += "completed";
478 break; 481 break;
479 case 1: 482 case 1:
480 query += "priority"; 483 query += "priority";
481 break; 484 break;
482 case 2: 485 case 2:
483 query += "summary"; 486 query += "summary";
484 break; 487 break;
485 case 3: 488 case 3:
486 query += "DueDate"; 489 query += "DueDate";
487 break; 490 break;
488 } 491 }
489 492
490 if ( !asc ) { 493 if ( !asc ) {
491 qWarning("not ascending!"); 494 qWarning("not ascending!");
492 query += " DESC"; 495 query += " DESC";
493 } 496 }
494 497
495 qWarning( query ); 498 qWarning( query );
496 OSQLRawQuery raw(query ); 499 OSQLRawQuery raw(query );
497 return uids( m_driver->query(&raw) ); 500 return uids( m_driver->query(&raw) );
498} 501}
499bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{ 502bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{
500 if ( str == "0-0-0" ) 503 if ( str == "0-0-0" )
501 return false; 504 return false;
502 else{ 505 else{
503 int day, year, month; 506 int day, year, month;
504 QStringList list = QStringList::split("-", str ); 507 QStringList list = QStringList::split("-", str );
505 year = list[0].toInt(); 508 year = list[0].toInt();
506 month = list[1].toInt(); 509 month = list[1].toInt();
507 day = list[2].toInt(); 510 day = list[2].toInt();
508 da.setYMD( year, month, day ); 511 da.setYMD( year, month, day );
509 return true; 512 return true;
510 } 513 }
511} 514}
512OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{ 515OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{
513 if ( res.state() == OSQLResult::Failure ) { 516 if ( res.state() == OSQLResult::Failure ) {
514 OTodo to; 517 OTodo to;
515 return to; 518 return to;
516 } 519 }
517 520
518 OSQLResultItem::ValueList list = res.results(); 521 OSQLResultItem::ValueList list = res.results();
519 OSQLResultItem::ValueList::Iterator it = list.begin(); 522 OSQLResultItem::ValueList::Iterator it = list.begin();
520 qWarning("todo1"); 523 qWarning("todo1");
521 OTodo to = todo( (*it) ); 524 OTodo to = todo( (*it) );
522 cache( to ); 525 cache( to );
523 ++it; 526 ++it;
524 527
525 for ( ; it != list.end(); ++it ) { 528 for ( ; it != list.end(); ++it ) {
526 qWarning("caching"); 529 qWarning("caching");
527 cache( todo( (*it) ) ); 530 cache( todo( (*it) ) );
528 } 531 }
529 return to; 532 return to;
530} 533}
531OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const { 534OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const {
532 qWarning("todo"); 535 qWarning("todo");
533 bool hasDueDate = false; QDate dueDate = QDate::currentDate(); 536 bool hasDueDate = false; QDate dueDate = QDate::currentDate();
534 hasDueDate = date( dueDate, item.data("DueDate") ); 537 hasDueDate = date( dueDate, item.data("DueDate") );
535 QStringList cats = QStringList::split(";", item.data("categories") ); 538 QStringList cats = QStringList::split(";", item.data("categories") );
536 539
537 qWarning("Item is completed: %d", item.data("completed").toInt() ); 540 qWarning("Item is completed: %d", item.data("completed").toInt() );
538 541
539 OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(), 542 OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(),
540 cats, item.data("summary"), item.data("description"), 543 cats, item.data("summary"), item.data("description"),
541 item.data("progress").toUShort(), hasDueDate, dueDate, 544 item.data("progress").toUShort(), hasDueDate, dueDate,
542 item.data("uid").toInt() ); 545 item.data("uid").toInt() );
543 546
544 bool isOk; 547 bool isOk;
545 int prioInt = QString( item.data("priority") ).toInt( &isOk ); 548 int prioInt = QString( item.data("priority") ).toInt( &isOk );
546 if ( isOk ) 549 if ( isOk )
547 to.setPriority( prioInt ); 550 to.setPriority( prioInt );
548 551
549 bool hasStartDate = false; QDate startDate = QDate::currentDate(); 552 bool hasStartDate = false; QDate startDate = QDate::currentDate();
550 hasStartDate = date( startDate, item.data("startdate") ); 553 hasStartDate = date( startDate, item.data("startdate") );
551 bool hasCompletedDate = false; QDate completedDate = QDate::currentDate(); 554 bool hasCompletedDate = false; QDate completedDate = QDate::currentDate();
552 hasCompletedDate = date( completedDate, item.data("completeddate") ); 555 hasCompletedDate = date( completedDate, item.data("completeddate") );
553 556
554 if ( hasStartDate ) 557 if ( hasStartDate )
555 to.setStartDate( startDate ); 558 to.setStartDate( startDate );
556 if ( hasCompletedDate ) 559 if ( hasCompletedDate )
557 to.setCompletedDate( completedDate ); 560 to.setCompletedDate( completedDate );
558 561
559 OPimNotifyManager& manager = to.notifiers(); 562 OPimNotifyManager& manager = to.notifiers();
560 manager.alarmsFromString( item.data("alarms") ); 563 manager.alarmsFromString( item.data("alarms") );
561 manager.remindersFromString( item.data("reminders") ); 564 manager.remindersFromString( item.data("reminders") );
562 565
563 OPimState pimState; 566 OPimState pimState;
564 pimState.setState( QString( item.data("state") ).toInt() ); 567 pimState.setState( QString( item.data("state") ).toInt() );
565 to.setState( pimState ); 568 to.setState( pimState );
566 569
567 QMap<int, QString> recMap; 570 QMap<int, QString> recMap;
568 recMap.insert( ORecur::RType , item.data("RType") ); 571 recMap.insert( ORecur::RType , item.data("RType") );
569 recMap.insert( ORecur::RWeekdays , item.data("RWeekdays") ); 572 recMap.insert( ORecur::RWeekdays , item.data("RWeekdays") );
570 recMap.insert( ORecur::RPosition , item.data("RPosition") ); 573 recMap.insert( ORecur::RPosition , item.data("RPosition") );
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
index 132c9fc..dd9dbde 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_sql.cpp
@@ -1,734 +1,743 @@
1/* 1/*
2 * SQL Backend for the OPIE-Contact Database. 2 * SQL Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * 5 *
6 * ===================================================================== 6 * =====================================================================
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * ===================================================================== 11 * =====================================================================
12 * ===================================================================== 12 * =====================================================================
13 * Version: $Id$ 13 * Version: $Id$
14 * ===================================================================== 14 * =====================================================================
15 * History: 15 * History:
16 * $Log$ 16 * $Log$
17 * Revision 1.3 2003/12/08 15:18:10 eilers
18 * Committing unfinished sql implementation before merging to libopie2 starts..
19 *
17 * Revision 1.2 2003/09/29 07:44:26 eilers 20 * Revision 1.2 2003/09/29 07:44:26 eilers
18 * Improvement of PIM-SQL Databases, but search queries are still limited. 21 * Improvement of PIM-SQL Databases, but search queries are still limited.
19 * Addressbook: Changed table layout. Now, we just need 1/3 of disk-space. 22 * Addressbook: Changed table layout. Now, we just need 1/3 of disk-space.
20 * Todo: Started to add new attributes. Some type conversions missing. 23 * Todo: Started to add new attributes. Some type conversions missing.
21 * 24 *
22 * Revision 1.1 2003/09/22 14:31:16 eilers 25 * Revision 1.1 2003/09/22 14:31:16 eilers
23 * Added first experimental incarnation of sql-backend for addressbook. 26 * Added first experimental incarnation of sql-backend for addressbook.
24 * Some modifications to be able to compile the todo sql-backend. 27 * Some modifications to be able to compile the todo sql-backend.
25 * A lot of changes fill follow... 28 * A lot of changes fill follow...
26 * 29 *
27 */ 30 */
28 31
29#include "ocontactaccessbackend_sql.h" 32#include "ocontactaccessbackend_sql.h"
30 33
31#include <qarray.h> 34#include <qarray.h>
32#include <qdatetime.h> 35#include <qdatetime.h>
33#include <qstringlist.h> 36#include <qstringlist.h>
34 37
35#include <qpe/global.h> 38#include <qpe/global.h>
36#include <qpe/recordfields.h> 39#include <qpe/recordfields.h>
37 40
38#include <opie/ocontactfields.h> 41#include <opie/ocontactfields.h>
39#include <opie/oconversion.h> 42#include <opie/oconversion.h>
40#include <opie2/osqldriver.h> 43#include <opie2/osqldriver.h>
41#include <opie2/osqlresult.h> 44#include <opie2/osqlresult.h>
42#include <opie2/osqlmanager.h> 45#include <opie2/osqlmanager.h>
43#include <opie2/osqlquery.h> 46#include <opie2/osqlquery.h>
44 47
45 48
46 49
47 50
48// If defined, we use a horizontal table ( uid, attr1, attr2, attr3, ..., attrn ) instead 51// If defined, we use a horizontal table ( uid, attr1, attr2, attr3, ..., attrn ) instead
49// vertical like "uid, type, value". 52// vertical like "uid, type, value".
50// DON'T DEACTIVATE THIS DEFINE IN PRODUCTIVE ENVIRONMENTS !! 53// DON'T DEACTIVATE THIS DEFINE IN PRODUCTIVE ENVIRONMENTS !!
51#define __STORE_HORIZONTAL_ 54#define __STORE_HORIZONTAL_
52 55
53// Distinct loading is not very fast. If I expect that every person has just 56// Distinct loading is not very fast. If I expect that every person has just
54// one (and always one) 'Last Name', I can request all uid's for existing lastnames, 57// one (and always one) 'Last Name', I can request all uid's for existing lastnames,
55// which is faster.. 58// which is faster..
56// But this may not be true for all entries, like company contacts.. 59// But this may not be true for all entries, like company contacts..
57// The current AddressBook application handles this problem, but other may not.. (eilers) 60// The current AddressBook application handles this problem, but other may not.. (eilers)
58#define __USE_SUPERFAST_LOADQUERY 61#define __USE_SUPERFAST_LOADQUERY
59 62
60 63
61/* 64/*
62 * Implementation of used query types 65 * Implementation of used query types
63 * CREATE query 66 * CREATE query
64 * LOAD query 67 * LOAD query
65 * INSERT 68 * INSERT
66 * REMOVE 69 * REMOVE
67 * CLEAR 70 * CLEAR
68 */ 71 */
69namespace { 72namespace {
70 /** 73 /**
71 * CreateQuery for the Todolist Table 74 * CreateQuery for the Todolist Table
72 */ 75 */
73 class CreateQuery : public OSQLQuery { 76 class CreateQuery : public OSQLQuery {
74 public: 77 public:
75 CreateQuery(); 78 CreateQuery();
76 ~CreateQuery(); 79 ~CreateQuery();
77 QString query()const; 80 QString query()const;
78 }; 81 };
79 82
80 /** 83 /**
81 * Clears (delete) a Table 84 * Clears (delete) a Table
82 */ 85 */
83 class ClearQuery : public OSQLQuery { 86 class ClearQuery : public OSQLQuery {
84 public: 87 public:
85 ClearQuery(); 88 ClearQuery();
86 ~ClearQuery(); 89 ~ClearQuery();
87 QString query()const; 90 QString query()const;
88 91
89 }; 92 };
90 93
91 94
92 /** 95 /**
93 * LoadQuery 96 * LoadQuery
94 * this one queries for all uids 97 * this one queries for all uids
95 */ 98 */
96 class LoadQuery : public OSQLQuery { 99 class LoadQuery : public OSQLQuery {
97 public: 100 public:
98 LoadQuery(); 101 LoadQuery();
99 ~LoadQuery(); 102 ~LoadQuery();
100 QString query()const; 103 QString query()const;
101 }; 104 };
102 105
103 /** 106 /**
104 * inserts/adds a OContact to the table 107 * inserts/adds a OContact to the table
105 */ 108 */
106 class InsertQuery : public OSQLQuery { 109 class InsertQuery : public OSQLQuery {
107 public: 110 public:
108 InsertQuery(const OContact& ); 111 InsertQuery(const OContact& );
109 ~InsertQuery(); 112 ~InsertQuery();
110 QString query()const; 113 QString query()const;
111 private: 114 private:
112 OContact m_contact; 115 OContact m_contact;
113 }; 116 };
114 117
115 118
116 /** 119 /**
117 * removes one from the table 120 * removes one from the table
118 */ 121 */
119 class RemoveQuery : public OSQLQuery { 122 class RemoveQuery : public OSQLQuery {
120 public: 123 public:
121 RemoveQuery(int uid ); 124 RemoveQuery(int uid );
122 ~RemoveQuery(); 125 ~RemoveQuery();
123 QString query()const; 126 QString query()const;
124 private: 127 private:
125 int m_uid; 128 int m_uid;
126 }; 129 };
127 130
128 /** 131 /**
129 * a find query for noncustom elements 132 * a find query for noncustom elements
130 */ 133 */
131 class FindQuery : public OSQLQuery { 134 class FindQuery : public OSQLQuery {
132 public: 135 public:
133 FindQuery(int uid); 136 FindQuery(int uid);
134 FindQuery(const QArray<int>& ); 137 FindQuery(const QArray<int>& );
135 ~FindQuery(); 138 ~FindQuery();
136 QString query()const; 139 QString query()const;
137 private: 140 private:
138 QString single()const; 141 QString single()const;
139 QString multi()const; 142 QString multi()const;
140 QArray<int> m_uids; 143 QArray<int> m_uids;
141 int m_uid; 144 int m_uid;
142 }; 145 };
143 146
144 /** 147 /**
145 * a find query for custom elements 148 * a find query for custom elements
146 */ 149 */
147 class FindCustomQuery : public OSQLQuery { 150 class FindCustomQuery : public OSQLQuery {
148 public: 151 public:
149 FindCustomQuery(int uid); 152 FindCustomQuery(int uid);
150 FindCustomQuery(const QArray<int>& ); 153 FindCustomQuery(const QArray<int>& );
151 ~FindCustomQuery(); 154 ~FindCustomQuery();
152 QString query()const; 155 QString query()const;
153 private: 156 private:
154 QString single()const; 157 QString single()const;
155 QString multi()const; 158 QString multi()const;
156 QArray<int> m_uids; 159 QArray<int> m_uids;
157 int m_uid; 160 int m_uid;
158 }; 161 };
159 162
160 163
161 164
162 // We using three tables to store the information: 165 // We using three tables to store the information:
163 // 1. addressbook : It contains General information about the contact (non custom) 166 // 1. addressbook : It contains General information about the contact (non custom)
164 // 2. custom_data : Not official supported entries 167 // 2. custom_data : Not official supported entries
165 // All tables are connected by the uid of the contact. 168 // All tables are connected by the uid of the contact.
166 // Maybe I should add a table for meta-information ? 169 // Maybe I should add a table for meta-information ?
167 CreateQuery::CreateQuery() : OSQLQuery() {} 170 CreateQuery::CreateQuery() : OSQLQuery() {}
168 CreateQuery::~CreateQuery() {} 171 CreateQuery::~CreateQuery() {}
169 QString CreateQuery::query()const { 172 QString CreateQuery::query()const {
170 QString qu; 173 QString qu;
171#ifdef __STORE_HORIZONTAL_ 174#ifdef __STORE_HORIZONTAL_
172 175
173 qu += "create table addressbook( uid PRIMARY KEY "; 176 qu += "create table addressbook( uid PRIMARY KEY ";
174 177
175 QStringList fieldList = OContactFields::untrfields( false ); 178 QStringList fieldList = OContactFields::untrfields( false );
176 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 179 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
177 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( *it ); 180 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( *it );
178 } 181 }
179 qu += " );"; 182 qu += " );";
180 183
181 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );"; 184 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
182 185
183#else 186#else
184 187
185 qu += "create table addressbook( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id));"; 188 qu += "create table addressbook( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id));";
186 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );"; 189 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
187 // qu += "create table dates( uid PRIMARY KEY, type, day, month, year, hour, minute, second );"; 190 // qu += "create table dates( uid PRIMARY KEY, type, day, month, year, hour, minute, second );";
188 191
189#endif // __STORE_HORIZONTAL_ 192#endif // __STORE_HORIZONTAL_
190 return qu; 193 return qu;
191 } 194 }
192 195
193 ClearQuery::ClearQuery() 196 ClearQuery::ClearQuery()
194 : OSQLQuery() {} 197 : OSQLQuery() {}
195 ClearQuery::~ClearQuery() {} 198 ClearQuery::~ClearQuery() {}
196 QString ClearQuery::query()const { 199 QString ClearQuery::query()const {
197 QString qu = "drop table addressbook;"; 200 QString qu = "drop table addressbook;";
198 qu += "drop table custom_data;"; 201 qu += "drop table custom_data;";
199 // qu += "drop table dates;"; 202 // qu += "drop table dates;";
200 return qu; 203 return qu;
201 } 204 }
202 205
203 206
204 LoadQuery::LoadQuery() : OSQLQuery() {} 207 LoadQuery::LoadQuery() : OSQLQuery() {}
205 LoadQuery::~LoadQuery() {} 208 LoadQuery::~LoadQuery() {}
206 QString LoadQuery::query()const { 209 QString LoadQuery::query()const {
207 QString qu; 210 QString qu;
208#ifdef __STORE_HORIZONTAL_ 211#ifdef __STORE_HORIZONTAL_
209 qu += "select uid from addressbook"; 212 qu += "select uid from addressbook";
210#else 213#else
211# ifndef __USE_SUPERFAST_LOADQUERY 214# ifndef __USE_SUPERFAST_LOADQUERY
212 qu += "select distinct uid from addressbook"; 215 qu += "select distinct uid from addressbook";
213# else 216# else
214 qu += "select uid from addressbook where type = 'Last Name'"; 217 qu += "select uid from addressbook where type = 'Last Name'";
215# endif // __USE_SUPERFAST_LOADQUERY 218# endif // __USE_SUPERFAST_LOADQUERY
216#endif // __STORE_HORIZONTAL_ 219#endif // __STORE_HORIZONTAL_
217 220
218 return qu; 221 return qu;
219 } 222 }
220 223
221 224
222 InsertQuery::InsertQuery( const OContact& contact ) 225 InsertQuery::InsertQuery( const OContact& contact )
223 : OSQLQuery(), m_contact( contact ) { 226 : OSQLQuery(), m_contact( contact ) {
224 } 227 }
225 228
226 InsertQuery::~InsertQuery() { 229 InsertQuery::~InsertQuery() {
227 } 230 }
228 231
229 /* 232 /*
230 * converts from a OContact to a query 233 * converts from a OContact to a query
231 */ 234 */
232 QString InsertQuery::query()const{ 235 QString InsertQuery::query()const{
233 236
234#ifdef __STORE_HORIZONTAL_ 237#ifdef __STORE_HORIZONTAL_
235 QString qu; 238 QString qu;
236 qu += "insert into addressbook VALUES( " + 239 qu += "insert into addressbook VALUES( " +
237 QString::number( m_contact.uid() ); 240 QString::number( m_contact.uid() );
238 241
239 // Get all information out of the contact-class 242 // Get all information out of the contact-class
240 // Remember: The category is stored in contactMap, too ! 243 // Remember: The category is stored in contactMap, too !
241 QMap<int, QString> contactMap = m_contact.toMap(); 244 QMap<int, QString> contactMap = m_contact.toMap();
242 245
243 QStringList fieldList = OContactFields::untrfields( false ); 246 QStringList fieldList = OContactFields::untrfields( false );
244 QMap<QString, int> translate = OContactFields::untrFieldsToId(); 247 QMap<QString, int> translate = OContactFields::untrFieldsToId();
245 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 248 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
246 // Convert Column-String to Id and get value for this id.. 249 // Convert Column-String to Id and get value for this id..
247 // Hmmm.. Maybe not very cute solution.. 250 // Hmmm.. Maybe not very cute solution..
248 int id = translate[*it]; 251 int id = translate[*it];
249 switch ( id ){ 252 switch ( id ){
250 case Qtopia::Birthday:{ 253 case Qtopia::Birthday:{
251 // These entries should stored in a special format 254 // These entries should stored in a special format
252 // year-month-day 255 // year-month-day
253 QDate day = m_contact.birthday(); 256 QDate day = m_contact.birthday();
254 if ( day.isValid() ){ 257 if ( day.isValid() ){
255 qu += QString(",\"%1-%2-%3\"") 258 qu += QString(",\"%1-%2-%3\"")
256 .arg( day.year() ) 259 .arg( day.year() )
257 .arg( day.month() ) 260 .arg( day.month() )
258 .arg( day.day() ); 261 .arg( day.day() );
259 } else { 262 } else {
260 qu += ",\"\""; 263 qu += ",\"\"";
261 } 264 }
262 } 265 }
263 break; 266 break;
264 case Qtopia::Anniversary:{ 267 case Qtopia::Anniversary:{
265 // These entries should stored in a special format 268 // These entries should stored in a special format
266 // year-month-day 269 // year-month-day
267 QDate day = m_contact.anniversary(); 270 QDate day = m_contact.anniversary();
268 if ( day.isValid() ){ 271 if ( day.isValid() ){
269 qu += QString(",\"%1-%2-%3\"") 272 qu += QString(",\"%1-%2-%3\"")
270 .arg( day.year() ) 273 .arg( day.year() )
271 .arg( day.month() ) 274 .arg( day.month() )
272 .arg( day.day() ); 275 .arg( day.day() );
273 } else { 276 } else {
274 qu += ",\"\""; 277 qu += ",\"\"";
275 } 278 }
276 } 279 }
277 break; 280 break;
278 281
279 default: 282 default:
280 qu += QString( ",\"%1\"" ).arg( contactMap[id] ); 283 qu += QString( ",\"%1\"" ).arg( contactMap[id] );
281 } 284 }
282 } 285 }
283 qu += " );"; 286 qu += " );";
284 287
285 288
286#else 289#else
287 // Get all information out of the contact-class 290 // Get all information out of the contact-class
288 // Remember: The category is stored in contactMap, too ! 291 // Remember: The category is stored in contactMap, too !
289 QMap<int, QString> contactMap = m_contact.toMap(); 292 QMap<int, QString> contactMap = m_contact.toMap();
290 293
291 QMap<QString, QString> addressbook_db; 294 QMap<QString, QString> addressbook_db;
292 295
293 // Get the translation from the ID to the String 296 // Get the translation from the ID to the String
294 QMap<int, QString> transMap = OContactFields::idToUntrFields(); 297 QMap<int, QString> transMap = OContactFields::idToUntrFields();
295 298
296 for( QMap<int, QString>::Iterator it = contactMap.begin(); 299 for( QMap<int, QString>::Iterator it = contactMap.begin();
297 it != contactMap.end(); ++it ){ 300 it != contactMap.end(); ++it ){
298 switch ( it.key() ){ 301 switch ( it.key() ){
299 case Qtopia::Birthday:{ 302 case Qtopia::Birthday:{
300 // These entries should stored in a special format 303 // These entries should stored in a special format
301 // year-month-day 304 // year-month-day
302 QDate day = m_contact.birthday(); 305 QDate day = m_contact.birthday();
303 addressbook_db.insert( transMap[it.key()], 306 addressbook_db.insert( transMap[it.key()],
304 QString("%1-%2-%3") 307 QString("%1-%2-%3")
305 .arg( day.year() ) 308 .arg( day.year() )
306 .arg( day.month() ) 309 .arg( day.month() )
307 .arg( day.day() ) ); 310 .arg( day.day() ) );
308 } 311 }
309 break; 312 break;
310 case Qtopia::Anniversary:{ 313 case Qtopia::Anniversary:{
311 // These entries should stored in a special format 314 // These entries should stored in a special format
312 // year-month-day 315 // year-month-day
313 QDate day = m_contact.anniversary(); 316 QDate day = m_contact.anniversary();
314 addressbook_db.insert( transMap[it.key()], 317 addressbook_db.insert( transMap[it.key()],
315 QString("%1-%2-%3") 318 QString("%1-%2-%3")
316 .arg( day.year() ) 319 .arg( day.year() )
317 .arg( day.month() ) 320 .arg( day.month() )
318 .arg( day.day() ) ); 321 .arg( day.day() ) );
319 } 322 }
320 break; 323 break;
321 case Qtopia::AddressUid: // Ignore UID 324 case Qtopia::AddressUid: // Ignore UID
322 break; 325 break;
323 default: // Translate id to String 326 default: // Translate id to String
324 addressbook_db.insert( transMap[it.key()], it.data() ); 327 addressbook_db.insert( transMap[it.key()], it.data() );
325 break; 328 break;
326 } 329 }
327 330
328 } 331 }
329 332
330 // Now convert this whole stuff into a SQL String, beginning with 333 // Now convert this whole stuff into a SQL String, beginning with
331 // the addressbook table.. 334 // the addressbook table..
332 QString qu; 335 QString qu;
333 // qu += "begin transaction;"; 336 // qu += "begin transaction;";
334 int id = 0; 337 int id = 0;
335 for( QMap<QString, QString>::Iterator it = addressbook_db.begin(); 338 for( QMap<QString, QString>::Iterator it = addressbook_db.begin();
336 it != addressbook_db.end(); ++it ){ 339 it != addressbook_db.end(); ++it ){
337 qu += "insert into addressbook VALUES(" 340 qu += "insert into addressbook VALUES("
338 + QString::number( m_contact.uid() ) 341 + QString::number( m_contact.uid() )
339 + "," 342 + ","
340 + QString::number( id++ ) 343 + QString::number( id++ )
341 + ",'" 344 + ",'"
342 + it.key() //.latin1() 345 + it.key() //.latin1()
343 + "'," 346 + "',"
344 + "0" // Priority for future enhancements 347 + "0" // Priority for future enhancements
345 + ",'" 348 + ",'"
346 + it.data() //.latin1() 349 + it.data() //.latin1()
347 + "');"; 350 + "');";
348 } 351 }
349 352
350 #endif //__STORE_HORIZONTAL_ 353 #endif //__STORE_HORIZONTAL_
351 // Now add custom data.. 354 // Now add custom data..
352#ifdef __STORE_HORIZONTAL_ 355#ifdef __STORE_HORIZONTAL_
353 int id = 0; 356 int id = 0;
354#endif 357#endif
355 id = 0; 358 id = 0;
356 QMap<QString, QString> customMap = m_contact.toExtraMap(); 359 QMap<QString, QString> customMap = m_contact.toExtraMap();
357 for( QMap<QString, QString>::Iterator it = customMap.begin(); 360 for( QMap<QString, QString>::Iterator it = customMap.begin();
358 it != customMap.end(); ++it ){ 361 it != customMap.end(); ++it ){
359 qu += "insert into custom_data VALUES(" 362 qu += "insert into custom_data VALUES("
360 + QString::number( m_contact.uid() ) 363 + QString::number( m_contact.uid() )
361 + "," 364 + ","
362 + QString::number( id++ ) 365 + QString::number( id++ )
363 + ",'" 366 + ",'"
364 + it.key() //.latin1() 367 + it.key() //.latin1()
365 + "'," 368 + "',"
366 + "0" // Priority for future enhancements 369 + "0" // Priority for future enhancements
367 + ",'" 370 + ",'"
368 + it.data() //.latin1() 371 + it.data() //.latin1()
369 + "');"; 372 + "');";
370 } 373 }
371 // qu += "commit;"; 374 // qu += "commit;";
372 qWarning("add %s", qu.latin1() ); 375 qWarning("add %s", qu.latin1() );
373 return qu; 376 return qu;
374 } 377 }
375 378
376 379
377 RemoveQuery::RemoveQuery(int uid ) 380 RemoveQuery::RemoveQuery(int uid )
378 : OSQLQuery(), m_uid( uid ) {} 381 : OSQLQuery(), m_uid( uid ) {}
379 RemoveQuery::~RemoveQuery() {} 382 RemoveQuery::~RemoveQuery() {}
380 QString RemoveQuery::query()const { 383 QString RemoveQuery::query()const {
381 QString qu = "DELETE from addressbook where uid = " 384 QString qu = "DELETE from addressbook where uid = "
382 + QString::number(m_uid) + ";"; 385 + QString::number(m_uid) + ";";
383 qu += "DELETE from custom_data where uid = " 386 qu += "DELETE from custom_data where uid = "
384 + QString::number(m_uid) + ";"; 387 + QString::number(m_uid) + ";";
385 return qu; 388 return qu;
386 } 389 }
387 390
388 391
389 392
390 393
391 FindQuery::FindQuery(int uid) 394 FindQuery::FindQuery(int uid)
392 : OSQLQuery(), m_uid( uid ) { 395 : OSQLQuery(), m_uid( uid ) {
393 } 396 }
394 FindQuery::FindQuery(const QArray<int>& ints) 397 FindQuery::FindQuery(const QArray<int>& ints)
395 : OSQLQuery(), m_uids( ints ){ 398 : OSQLQuery(), m_uids( ints ){
396 } 399 }
397 FindQuery::~FindQuery() { 400 FindQuery::~FindQuery() {
398 } 401 }
399 QString FindQuery::query()const{ 402 QString FindQuery::query()const{
400 // if ( m_uids.count() == 0 ) 403 // if ( m_uids.count() == 0 )
401 return single(); 404 return single();
402 } 405 }
403 /* 406 /*
404 else 407 else
405 return multi(); 408 return multi();
406 } 409 }
407 QString FindQuery::multi()const { 410 QString FindQuery::multi()const {
408 QString qu = "select uid, type, value from addressbook where"; 411 QString qu = "select uid, type, value from addressbook where";
409 for (uint i = 0; i < m_uids.count(); i++ ) { 412 for (uint i = 0; i < m_uids.count(); i++ ) {
410 qu += " UID = " + QString::number( m_uids[i] ) + " OR"; 413 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
411 } 414 }
412 qu.remove( qu.length()-2, 2 ); // Hmmmm.. 415 qu.remove( qu.length()-2, 2 ); // Hmmmm..
413 return qu; 416 return qu;
414 } 417 }
415 */ 418 */
416#ifdef __STORE_HORIZONTAL_ 419#ifdef __STORE_HORIZONTAL_
417 QString FindQuery::single()const{ 420 QString FindQuery::single()const{
418 QString qu = "select *"; 421 QString qu = "select *";
419 qu += " from addressbook where uid = " + QString::number(m_uid); 422 qu += " from addressbook where uid = " + QString::number(m_uid);
420 423
421 // qWarning("find query: %s", qu.latin1() ); 424 // qWarning("find query: %s", qu.latin1() );
422 return qu; 425 return qu;
423 } 426 }
424#else 427#else
425 QString FindQuery::single()const{ 428 QString FindQuery::single()const{
426 QString qu = "select uid, type, value from addressbook where uid = "; 429 QString qu = "select uid, type, value from addressbook where uid = ";
427 qu += QString::number(m_uid); 430 qu += QString::number(m_uid);
428 return qu; 431 return qu;
429 } 432 }
430#endif 433#endif
431 434
432 435
433 FindCustomQuery::FindCustomQuery(int uid) 436 FindCustomQuery::FindCustomQuery(int uid)
434 : OSQLQuery(), m_uid( uid ) { 437 : OSQLQuery(), m_uid( uid ) {
435 } 438 }
436 FindCustomQuery::FindCustomQuery(const QArray<int>& ints) 439 FindCustomQuery::FindCustomQuery(const QArray<int>& ints)
437 : OSQLQuery(), m_uids( ints ){ 440 : OSQLQuery(), m_uids( ints ){
438 } 441 }
439 FindCustomQuery::~FindCustomQuery() { 442 FindCustomQuery::~FindCustomQuery() {
440 } 443 }
441 QString FindCustomQuery::query()const{ 444 QString FindCustomQuery::query()const{
442 // if ( m_uids.count() == 0 ) 445 // if ( m_uids.count() == 0 )
443 return single(); 446 return single();
444 } 447 }
445 QString FindCustomQuery::single()const{ 448 QString FindCustomQuery::single()const{
446 QString qu = "select uid, type, value from custom_data where uid = "; 449 QString qu = "select uid, type, value from custom_data where uid = ";
447 qu += QString::number(m_uid); 450 qu += QString::number(m_uid);
448 return qu; 451 return qu;
449 } 452 }
450 453
451}; 454};
452 455
453 456
454/* --------------------------------------------------------------------------- */ 457/* --------------------------------------------------------------------------- */
455 458
456OContactAccessBackend_SQL::OContactAccessBackend_SQL ( const QString& /* appname */, 459OContactAccessBackend_SQL::OContactAccessBackend_SQL ( const QString& /* appname */,
457 const QString& filename ): m_changed(false) 460 const QString& filename ):
461 OContactAccessBackend(), m_changed(false), m_driver( NULL )
458{ 462{
459 qWarning("C'tor OContactAccessBackend_SQL starts"); 463 qWarning("C'tor OContactAccessBackend_SQL starts");
460 QTime t; 464 QTime t;
461 t.start(); 465 t.start();
462 466
463 /* Expecting to access the default filename if nothing else is set */ 467 /* Expecting to access the default filename if nothing else is set */
464 if ( filename.isEmpty() ){ 468 if ( filename.isEmpty() ){
465 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" ); 469 m_fileName = Global::applicationFileName( "addressbook","addressbook.db" );
466 } else 470 } else
467 m_fileName = filename; 471 m_fileName = filename;
468 472
469 // Get the standart sql-driver from the OSQLManager.. 473 // Get the standart sql-driver from the OSQLManager..
470 OSQLManager man; 474 OSQLManager man;
471 m_driver = man.standard(); 475 m_driver = man.standard();
472 m_driver->setUrl( m_fileName ); 476 m_driver->setUrl( m_fileName );
473 477
474 load(); 478 load();
475 479
476 qWarning("C'tor OContactAccessBackend_SQL ends: %d ms", t.elapsed() ); 480 qWarning("C'tor OContactAccessBackend_SQL ends: %d ms", t.elapsed() );
477} 481}
478 482
483OContactAccessBackend_SQL::~OContactAccessBackend_SQL ()
484{
485 if( m_driver )
486 delete m_driver;
487}
479 488
480bool OContactAccessBackend_SQL::load () 489bool OContactAccessBackend_SQL::load ()
481{ 490{
482 if (!m_driver->open() ) 491 if (!m_driver->open() )
483 return false; 492 return false;
484 493
485 // Don't expect that the database exists. 494 // Don't expect that the database exists.
486 // It is save here to create the table, even if it 495 // It is save here to create the table, even if it
487 // do exist. ( Is that correct for all databases ?? ) 496 // do exist. ( Is that correct for all databases ?? )
488 CreateQuery creat; 497 CreateQuery creat;
489 OSQLResult res = m_driver->query( &creat ); 498 OSQLResult res = m_driver->query( &creat );
490 499
491 update(); 500 update();
492 501
493 return true; 502 return true;
494 503
495} 504}
496 505
497bool OContactAccessBackend_SQL::reload() 506bool OContactAccessBackend_SQL::reload()
498{ 507{
499 return load(); 508 return load();
500} 509}
501 510
502bool OContactAccessBackend_SQL::save() 511bool OContactAccessBackend_SQL::save()
503{ 512{
504 return m_driver->close(); 513 return m_driver->close();
505} 514}
506 515
507 516
508void OContactAccessBackend_SQL::clear () 517void OContactAccessBackend_SQL::clear ()
509{ 518{
510 ClearQuery cle; 519 ClearQuery cle;
511 OSQLResult res = m_driver->query( &cle ); 520 OSQLResult res = m_driver->query( &cle );
512 CreateQuery qu; 521 CreateQuery qu;
513 res = m_driver->query(&qu); 522 res = m_driver->query(&qu);
514} 523}
515 524
516bool OContactAccessBackend_SQL::wasChangedExternally() 525bool OContactAccessBackend_SQL::wasChangedExternally()
517{ 526{
518 return false; 527 return false;
519} 528}
520 529
521QArray<int> OContactAccessBackend_SQL::allRecords() const 530QArray<int> OContactAccessBackend_SQL::allRecords() const
522{ 531{
523 532
524 // FIXME: Think about cute handling of changed tables.. 533 // FIXME: Think about cute handling of changed tables..
525 // Thus, we don't have to call update here... 534 // Thus, we don't have to call update here...
526 if ( m_changed ) 535 if ( m_changed )
527 ((OContactAccessBackend_SQL*)this)->update(); 536 ((OContactAccessBackend_SQL*)this)->update();
528 537
529 return m_uids; 538 return m_uids;
530} 539}
531 540
532bool OContactAccessBackend_SQL::add ( const OContact &newcontact ) 541bool OContactAccessBackend_SQL::add ( const OContact &newcontact )
533{ 542{
534 InsertQuery ins( newcontact ); 543 InsertQuery ins( newcontact );
535 OSQLResult res = m_driver->query( &ins ); 544 OSQLResult res = m_driver->query( &ins );
536 545
537 if ( res.state() == OSQLResult::Failure ) 546 if ( res.state() == OSQLResult::Failure )
538 return false; 547 return false;
539 548
540 int c = m_uids.count(); 549 int c = m_uids.count();
541 m_uids.resize( c+1 ); 550 m_uids.resize( c+1 );
542 m_uids[c] = newcontact.uid(); 551 m_uids[c] = newcontact.uid();
543 552
544 return true; 553 return true;
545} 554}
546 555
547 556
548bool OContactAccessBackend_SQL::remove ( int uid ) 557bool OContactAccessBackend_SQL::remove ( int uid )
549{ 558{
550 RemoveQuery rem( uid ); 559 RemoveQuery rem( uid );
551 OSQLResult res = m_driver->query(&rem ); 560 OSQLResult res = m_driver->query(&rem );
552 561
553 if ( res.state() == OSQLResult::Failure ) 562 if ( res.state() == OSQLResult::Failure )
554 return false; 563 return false;
555 564
556 m_changed = true; 565 m_changed = true;
557 566
558 return true; 567 return true;
559} 568}
560 569
561bool OContactAccessBackend_SQL::replace ( const OContact &contact ) 570bool OContactAccessBackend_SQL::replace ( const OContact &contact )
562{ 571{
563 if ( !remove( contact.uid() ) ) 572 if ( !remove( contact.uid() ) )
564 return false; 573 return false;
565 574
566 return add( contact ); 575 return add( contact );
567} 576}
568 577
569 578
570OContact OContactAccessBackend_SQL::find ( int uid ) const 579OContact OContactAccessBackend_SQL::find ( int uid ) const
571{ 580{
572 qWarning("OContactAccessBackend_SQL::find()"); 581 qWarning("OContactAccessBackend_SQL::find()");
573 QTime t; 582 QTime t;
574 t.start(); 583 t.start();
575 584
576 OContact retContact( requestNonCustom( uid ) ); 585 OContact retContact( requestNonCustom( uid ) );
577 retContact.setExtraMap( requestCustom( uid ) ); 586 retContact.setExtraMap( requestCustom( uid ) );
578 587
579 qWarning("OContactAccessBackend_SQL::find() needed: %d ms", t.elapsed() ); 588 qWarning("OContactAccessBackend_SQL::find() needed: %d ms", t.elapsed() );
580 return retContact; 589 return retContact;
581} 590}
582 591
583 592
584 593
585QArray<int> OContactAccessBackend_SQL::queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() ) 594QArray<int> OContactAccessBackend_SQL::queryByExample ( const OContact &query, int settings, const QDateTime& d = QDateTime() )
586{ 595{
587 QString qu = "SELECT uid FROM addressbook WHERE"; 596 QString qu = "SELECT uid FROM addressbook WHERE";
588 597
589 QMap<int, QString> queryFields = query.toMap(); 598 QMap<int, QString> queryFields = query.toMap();
590 QStringList fieldList = OContactFields::untrfields( false ); 599 QStringList fieldList = OContactFields::untrfields( false );
591 QMap<QString, int> translate = OContactFields::untrFieldsToId(); 600 QMap<QString, int> translate = OContactFields::untrFieldsToId();
592 601
593 // Convert every filled field to a SQL-Query 602 // Convert every filled field to a SQL-Query
594 bool isAnyFieldSelected = false; 603 bool isAnyFieldSelected = false;
595 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){ 604 for ( QStringList::Iterator it = ++fieldList.begin(); it != fieldList.end(); ++it ){
596 int id = translate[*it]; 605 int id = translate[*it];
597 QString queryStr = queryFields[id]; 606 QString queryStr = queryFields[id];
598 if ( !queryStr.isEmpty() ){ 607 if ( !queryStr.isEmpty() ){
599 isAnyFieldSelected = true; 608 isAnyFieldSelected = true;
600 switch( id ){ 609 switch( id ){
601 default: 610 default:
602 // Switching between case sensitive and insensitive... 611 // Switching between case sensitive and insensitive...
603 // LIKE is not case sensitive, GLOB is case sensitive 612 // LIKE is not case sensitive, GLOB is case sensitive
604 // Do exist a better solution to switch this ? 613 // Do exist a better solution to switch this ?
605 if ( settings & OContactAccess::IgnoreCase ) 614 if ( settings & OContactAccess::IgnoreCase )
606 qu += "(\"" + *it + "\"" + " LIKE " + "'" 615 qu += "(\"" + *it + "\"" + " LIKE " + "'"
607 + queryStr.replace(QRegExp("\\*"),"%") + "'" + ") AND "; 616 + queryStr.replace(QRegExp("\\*"),"%") + "'" + ") AND ";
608 else 617 else
609 qu += "(\"" + *it + "\"" + " GLOB " + "'" 618 qu += "(\"" + *it + "\"" + " GLOB " + "'"
610 + queryStr + "'" + ") AND "; 619 + queryStr + "'" + ") AND ";
611 620
612 } 621 }
613 } 622 }
614 } 623 }
615 // Skip trailing "AND" 624 // Skip trailing "AND"
616 if ( isAnyFieldSelected ) 625 if ( isAnyFieldSelected )
617 qu = qu.left( qu.length() - 4 ); 626 qu = qu.left( qu.length() - 4 );
618 627
619 qWarning( "queryByExample query: %s", qu.latin1() ); 628 qWarning( "queryByExample query: %s", qu.latin1() );
620 629
621 // Execute query and return the received uid's 630 // Execute query and return the received uid's
622 OSQLRawQuery raw( qu ); 631 OSQLRawQuery raw( qu );
623 OSQLResult res = m_driver->query( &raw ); 632 OSQLResult res = m_driver->query( &raw );
624 if ( res.state() != OSQLResult::Success ){ 633 if ( res.state() != OSQLResult::Success ){
625 QArray<int> empty; 634 QArray<int> empty;
626 return empty; 635 return empty;
627 } 636 }
628 637
629 QArray<int> list = extractUids( res ); 638 QArray<int> list = extractUids( res );
630 639
631 return list; 640 return list;
632} 641}
633 642
634QArray<int> OContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const 643QArray<int> OContactAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
635{ 644{
636 QArray<int> nix(0); 645 QArray<int> nix(0);
637 return nix; 646 return nix;
638} 647}
639 648
640const uint OContactAccessBackend_SQL::querySettings() 649const uint OContactAccessBackend_SQL::querySettings()
641{ 650{
642 return OContactAccess::IgnoreCase 651 return OContactAccess::IgnoreCase
643 || OContactAccess::WildCards; 652 || OContactAccess::WildCards;
644} 653}
645 654
646bool OContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const 655bool OContactAccessBackend_SQL::hasQuerySettings (uint querySettings) const
647{ 656{
648 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay 657 /* OContactAccess::IgnoreCase, DateDiff, DateYear, DateMonth, DateDay
649 * may be added with any of the other settings. IgnoreCase should never used alone. 658 * may be added with any of the other settings. IgnoreCase should never used alone.
650 * Wildcards, RegExp, ExactMatch should never used at the same time... 659 * Wildcards, RegExp, ExactMatch should never used at the same time...
651 */ 660 */
652 661
653 // Step 1: Check whether the given settings are supported by this backend 662 // Step 1: Check whether the given settings are supported by this backend
654 if ( ( querySettings & ( 663 if ( ( querySettings & (
655 OContactAccess::IgnoreCase 664 OContactAccess::IgnoreCase
656 | OContactAccess::WildCards 665 | OContactAccess::WildCards
657 // | OContactAccess::DateDiff 666 // | OContactAccess::DateDiff
658 // | OContactAccess::DateYear 667 // | OContactAccess::DateYear
659 // | OContactAccess::DateMonth 668 // | OContactAccess::DateMonth
660 // | OContactAccess::DateDay 669 // | OContactAccess::DateDay
661 // | OContactAccess::RegExp 670 // | OContactAccess::RegExp
662 // | OContactAccess::ExactMatch 671 // | OContactAccess::ExactMatch
663 ) ) != querySettings ) 672 ) ) != querySettings )
664 return false; 673 return false;
665 674
666 // Step 2: Check whether the given combinations are ok.. 675 // Step 2: Check whether the given combinations are ok..
667 676
668 // IngoreCase alone is invalid 677 // IngoreCase alone is invalid
669 if ( querySettings == OContactAccess::IgnoreCase ) 678 if ( querySettings == OContactAccess::IgnoreCase )
670 return false; 679 return false;
671 680
672 // WildCards, RegExp and ExactMatch should never used at the same time 681 // WildCards, RegExp and ExactMatch should never used at the same time
673 switch ( querySettings & ~( OContactAccess::IgnoreCase 682 switch ( querySettings & ~( OContactAccess::IgnoreCase
674 | OContactAccess::DateDiff 683 | OContactAccess::DateDiff
675 | OContactAccess::DateYear 684 | OContactAccess::DateYear
676 | OContactAccess::DateMonth 685 | OContactAccess::DateMonth
677 | OContactAccess::DateDay 686 | OContactAccess::DateDay
678 ) 687 )
679 ){ 688 ){
680 case OContactAccess::RegExp: 689 case OContactAccess::RegExp:
681 return ( true ); 690 return ( true );
682 case OContactAccess::WildCards: 691 case OContactAccess::WildCards:
683 return ( true ); 692 return ( true );
684 case OContactAccess::ExactMatch: 693 case OContactAccess::ExactMatch:
685 return ( true ); 694 return ( true );
686 case 0: // one of the upper removed bits were set.. 695 case 0: // one of the upper removed bits were set..
687 return ( true ); 696 return ( true );
688 default: 697 default:
689 return ( false ); 698 return ( false );
690 } 699 }
691 700
692} 701}
693 702
694QArray<int> OContactAccessBackend_SQL::sorted( bool asc, int , int , int ) 703QArray<int> OContactAccessBackend_SQL::sorted( bool asc, int , int , int )
695{ 704{
696 QTime t; 705 QTime t;
697 t.start(); 706 t.start();
698 707
699#ifdef __STORE_HORIZONTAL_ 708#ifdef __STORE_HORIZONTAL_
700 QString query = "SELECT uid FROM addressbook "; 709 QString query = "SELECT uid FROM addressbook ";
701 query += "ORDER BY \"Last Name\" "; 710 query += "ORDER BY \"Last Name\" ";
702#else 711#else
703 QString query = "SELECT uid FROM addressbook WHERE type = 'Last Name' "; 712 QString query = "SELECT uid FROM addressbook WHERE type = 'Last Name' ";
704 query += "ORDER BY upper( value )"; 713 query += "ORDER BY upper( value )";
705#endif 714#endif
706 715
707 if ( !asc ) 716 if ( !asc )
708 query += "DESC"; 717 query += "DESC";
709 718
710 // qWarning("sorted query is: %s", query.latin1() ); 719 // qWarning("sorted query is: %s", query.latin1() );
711 720
712 OSQLRawQuery raw( query ); 721 OSQLRawQuery raw( query );
713 OSQLResult res = m_driver->query( &raw ); 722 OSQLResult res = m_driver->query( &raw );
714 if ( res.state() != OSQLResult::Success ){ 723 if ( res.state() != OSQLResult::Success ){
715 QArray<int> empty; 724 QArray<int> empty;
716 return empty; 725 return empty;
717 } 726 }
718 727
719 QArray<int> list = extractUids( res ); 728 QArray<int> list = extractUids( res );
720 729
721 qWarning("sorted needed %d ms!", t.elapsed() ); 730 qWarning("sorted needed %d ms!", t.elapsed() );
722 return list; 731 return list;
723} 732}
724 733
725 734
726void OContactAccessBackend_SQL::update() 735void OContactAccessBackend_SQL::update()
727{ 736{
728 qWarning("Update starts"); 737 qWarning("Update starts");
729 QTime t; 738 QTime t;
730 t.start(); 739 t.start();
731 740
732 // Now load the database set and extract the uid's 741 // Now load the database set and extract the uid's
733 // which will be held locally 742 // which will be held locally
734 743
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_sql.h b/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
index bb22551..b8f1d8d 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_sql.h
@@ -1,96 +1,101 @@
1/* 1/*
2 * SQL Backend for the OPIE-Contact Database. 2 * SQL Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 4 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
5 * 5 *
6 * ===================================================================== 6 * =====================================================================
7 *This program is free software; you can redistribute it and/or 7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public 8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
11 * ===================================================================== 11 * =====================================================================
12 * 12 *
13 * 13 *
14 * ===================================================================== 14 * =====================================================================
15 * Version: $Id$ 15 * Version: $Id$
16 * ===================================================================== 16 * =====================================================================
17 * History: 17 * History:
18 * $Log$ 18 * $Log$
19 * Revision 1.2 2003/12/08 15:18:11 eilers
20 * Committing unfinished sql implementation before merging to libopie2 starts..
21 *
19 * Revision 1.1 2003/09/22 14:31:16 eilers 22 * Revision 1.1 2003/09/22 14:31:16 eilers
20 * Added first experimental incarnation of sql-backend for addressbook. 23 * Added first experimental incarnation of sql-backend for addressbook.
21 * Some modifications to be able to compile the todo sql-backend. 24 * Some modifications to be able to compile the todo sql-backend.
22 * A lot of changes fill follow... 25 * A lot of changes fill follow...
23 * 26 *
24 * 27 *
25 */ 28 */
26 29
27#ifndef _OContactAccessBackend_SQL_ 30#ifndef _OContactAccessBackend_SQL_
28#define _OContactAccessBackend_SQL_ 31#define _OContactAccessBackend_SQL_
29 32
30#include "ocontactaccessbackend.h" 33#include "ocontactaccessbackend.h"
31#include "ocontactaccess.h" 34#include "ocontactaccess.h"
32 35
33#include <qlist.h> 36#include <qlist.h>
34#include <qdict.h> 37#include <qdict.h>
35 38
36class OSQLDriver; 39class OSQLDriver;
37class OSQLResult; 40class OSQLResult;
38class OSQLResultItem; 41class OSQLResultItem;
39 42
40/* the default xml implementation */ 43/* the default xml implementation */
41/** 44/**
42 * This class is the SQL implementation of a Contact backend 45 * This class is the SQL implementation of a Contact backend
43 * it does implement everything available for OContact. 46 * it does implement everything available for OContact.
44 * @see OPimAccessBackend for more information of available methods 47 * @see OPimAccessBackend for more information of available methods
45 */ 48 */
46class OContactAccessBackend_SQL : public OContactAccessBackend { 49class OContactAccessBackend_SQL : public OContactAccessBackend {
47 public: 50 public:
48 OContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null ); 51 OContactAccessBackend_SQL ( const QString& appname, const QString& filename = QString::null );
49 52
53 ~OContactAccessBackend_SQL ();
54
50 bool save(); 55 bool save();
51 56
52 bool load (); 57 bool load ();
53 58
54 void clear (); 59 void clear ();
55 60
56 bool wasChangedExternally(); 61 bool wasChangedExternally();
57 62
58 QArray<int> allRecords() const; 63 QArray<int> allRecords() const;
59 64
60 OContact find ( int uid ) const; 65 OContact find ( int uid ) const;
61 // FIXME: Add lookahead-cache support ! 66 // FIXME: Add lookahead-cache support !
62 //OContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const; 67 //OContact find(int uid, const QArray<int>&, uint cur, Frontend::CacheDirection )const;
63 68
64 QArray<int> queryByExample ( const OContact &query, int settings, 69 QArray<int> queryByExample ( const OContact &query, int settings,
65 const QDateTime& d ); 70 const QDateTime& d );
66 71
67 QArray<int> matchRegexp( const QRegExp &r ) const; 72 QArray<int> matchRegexp( const QRegExp &r ) const;
68 73
69 const uint querySettings(); 74 const uint querySettings();
70 75
71 bool hasQuerySettings (uint querySettings) const; 76 bool hasQuerySettings (uint querySettings) const;
72 77
73 // Currently only asc implemented.. 78 // Currently only asc implemented..
74 QArray<int> sorted( bool asc, int , int , int ); 79 QArray<int> sorted( bool asc, int , int , int );
75 bool add ( const OContact &newcontact ); 80 bool add ( const OContact &newcontact );
76 81
77 bool replace ( const OContact &contact ); 82 bool replace ( const OContact &contact );
78 83
79 bool remove ( int uid ); 84 bool remove ( int uid );
80 bool reload(); 85 bool reload();
81 86
82 private: 87 private:
83 QArray<int> extractUids( OSQLResult& res ) const; 88 QArray<int> extractUids( OSQLResult& res ) const;
84 QMap<int, QString> requestNonCustom( int uid ) const; 89 QMap<int, QString> requestNonCustom( int uid ) const;
85 QMap<QString, QString> requestCustom( int uid ) const; 90 QMap<QString, QString> requestCustom( int uid ) const;
86 void update(); 91 void update();
87 92
88 protected: 93 protected:
89 bool m_changed; 94 bool m_changed;
90 QString m_fileName; 95 QString m_fileName;
91 QArray<int> m_uids; 96 QArray<int> m_uids;
92 97
93 OSQLDriver* m_driver; 98 OSQLDriver* m_driver;
94}; 99};
95 100
96#endif 101#endif
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp
new file mode 100644
index 0000000..9769bf7
--- a/dev/null
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_sql.cpp
@@ -0,0 +1,221 @@
1/*
2 * SQL Backend for the OPIE-Calender Database.
3 *
4 * Copyright (c) 2003 by Stefan Eilers (Eilers.Stefan@epost.de)
5 *
6 * =====================================================================
7 *This program is free software; you can redistribute it and/or
8 *modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 * =====================================================================
12 * =====================================================================
13 * Version: $Id$
14 * =====================================================================
15 * History:
16 * $Log$
17 * Revision 1.1 2003/12/08 15:18:12 eilers
18 * Committing unfinished sql implementation before merging to libopie2 starts..
19 *
20 *
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25
26#include <qarray.h>
27#include <qstringlist.h>
28
29#include "orecur.h"
30#include "odatebookaccessbackend_sql.h"
31
32#include <opie2/osqldriver.h>
33#include <opie2/osqlresult.h>
34#include <opie2/osqlmanager.h>
35#include <opie2/osqlquery.h>
36
37namespace {
38
39
40
41};
42
43ODateBookAccessBackend_SQL::ODateBookAccessBackend_SQL( const QString& ,
44 const QString& fileName )
45 : ODateBookAccessBackend(), m_driver( NULL )
46{
47 m_fileName = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.db" ) : fileName;
48
49 // Get the standart sql-driver from the OSQLManager..
50 OSQLManager man;
51 m_driver = man.standard();
52 m_driver->setUrl( m_fileName );
53
54 initFields();
55
56 load();
57}
58
59ODateBookAccessBackend_SQL::~ODateBookAccessBackend_SQL() {
60}
61
62void ODateBookAccessBackend_SQL::initFields()
63{
64
65 // This map contains the translation of the fieldtype id's to
66 // the names of the table columns
67 m_fieldMap.insert( OEvent::FUid, "uid" );
68 m_fieldMap.insert( OEvent::FCategories, "Categories" );
69 m_fieldMap.insert( OEvent::FDescription, "Description" );
70 m_fieldMap.insert( OEvent::FLocation, "Location" );
71 m_fieldMap.insert( OEvent::FType, "Type" );
72 m_fieldMap.insert( OEvent::FAlarm, "Alarm" );
73 m_fieldMap.insert( OEvent::FSound, "Sound" );
74 m_fieldMap.insert( OEvent::FRType, "RType" );
75 m_fieldMap.insert( OEvent::FRWeekdays, "RWeekdays" );
76 m_fieldMap.insert( OEvent::FRPosition, "RPosition" );
77 m_fieldMap.insert( OEvent::FRFreq, "RFreq" );
78 m_fieldMap.insert( OEvent::FRHasEndDate, "RHasEndDate" );
79 m_fieldMap.insert( OEvent::FREndDate, "REndDate" );
80 m_fieldMap.insert( OEvent::FRCreated, "RCreated" );
81 m_fieldMap.insert( OEvent::FRExeptions, "RExceptions" );
82 m_fieldMap.insert( OEvent::FStart, "Start" );
83 m_fieldMap.insert( OEvent::FEnd, "End" );
84 m_fieldMap.insert( OEvent::FNote, "Note" );
85 m_fieldMap.insert( OEvent::FTimeZone, "TimeZone" );
86 m_fieldMap.insert( OEvent::FRecParent, "RecParent" );
87 m_fieldMap.insert( OEvent::FRecChildren, "Recchildren" );
88}
89
90bool ODateBookAccessBackend_SQL::load()
91{
92 if (!m_driver->open() )
93 return false;
94
95 // Don't expect that the database exists.
96 // It is save here to create the table, even if it
97 // do exist. ( Is that correct for all databases ?? )
98 QStringqu = "create table datebook( uid INTEGER PRIMARY KEY ";
99
100 QMap<int, QString>::Iterator it;
101 for ( it = ++m_fieldMap.begin(); it != m_fieldMap.end(); ++it ){
102 qu += QString( ",\"%1\" VARCHAR(10)" ).arg( it.data() );
103 }
104 qu += " );";
105
106 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR, priority INTEGER, value VARCHAR, PRIMARY KEY /* identifier */ (uid, id) );";
107
108 OSQLRawQuery raw( qu );
109 OSQLResult res = m_driver->query( &raw );
110 if ( res.state() != OSQLResult::Success )
111 return false;
112
113 update();
114
115 return true;
116}
117
118void ODateBookAccessBackend_SQL::update()
119{
120
121 QString qu = "select uid from datebook";
122 OSQLRawQuery raw( qu );
123 OSQLResult res = m_driver->query( &raw );
124 if ( res.state() != OSQLResult::Success ){
125 m_uids.clear();
126 return;
127 }
128
129 m_uids = extractUids( res );
130
131}
132
133QArray<int> ODateBookAccessBackend_SQL::extractUids( OSQLResult& res ) const
134{
135 qWarning("extractUids");
136
137 OSQLResultItem::ValueList list = res.results();
138 OSQLResultItem::ValueList::Iterator it;
139 QArray<int> ints(list.count() );
140 qWarning(" count = %d", list.count() );
141
142 int i = 0;
143 for (it = list.begin(); it != list.end(); ++it ) {
144 ints[i] = (*it).data("uid").toInt();
145 i++;
146 }
147
148 return ints;
149
150}
151
152bool ODateBookAccessBackend_SQL::reload()
153{
154 return load();
155}
156
157bool ODateBookAccessBackend_SQL::save()
158{
159 return m_driver->close();
160}
161
162QArray<int> ODateBookAccessBackend_SQL::allRecords()const
163{
164 return m_uids;
165}
166
167QArray<int> ODateBookAccessBackend_SQL::queryByExample(const OEvent&, int, const QDateTime& ) {
168 return QArray<int>();
169}
170
171void ODateBookAccessBackend_SQL::clear()
172{
173 QString qu = "drop table datebook;";
174 qu += "drop table custom_data;";
175
176 OSQLRawQuery raw( qu );
177 OSQLResult res = m_driver->query( &raw );
178
179}
180
181
182OEvent ODateBookAccessBackend_SQL::find( int uid ) const{
183}
184
185bool ODateBookAccessBackend_SQL::add( const OEvent& ev ) {
186 return true;
187}
188bool ODateBookAccessBackend_SQL::remove( int uid ) {
189
190 return true;
191}
192bool ODateBookAccessBackend_SQL::replace( const OEvent& ev ) {
193 remove( ev.uid() );
194 return add( ev );
195}
196QArray<int> ODateBookAccessBackend_SQL::rawEvents()const {
197 return allRecords();
198}
199QArray<int> ODateBookAccessBackend_SQL::rawRepeats()const {
200
201 return ints;
202}
203QArray<int> ODateBookAccessBackend_SQL::nonRepeats()const {
204
205 return ints;
206}
207OEvent::ValueList ODateBookAccessBackend_SQL::directNonRepeats() {
208
209 return list;
210}
211OEvent::ValueList ODateBookAccessBackend_SQL::directRawRepeats() {
212
213 return list;
214}
215
216
217QArray<int> ODateBookAccessBackend_SQL::matchRegexp( const QRegExp &r ) const
218{
219
220 return m_currentQuery;
221}
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_sql.h b/libopie2/opiepim/backend/odatebookaccessbackend_sql.h
new file mode 100644
index 0000000..85e0d4f
--- a/dev/null
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_sql.h
@@ -0,0 +1,60 @@
1#ifndef OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
2#define OPIE_DATE_BOOK_ACCESS_BACKEND_SQL__H
3
4#include <qmap.h>
5
6#include "odatebookaccessbackend.h"
7
8class OSQLDriver;
9
10/**
11 * This is the default SQL implementation for DateBoook SQL storage
12 * It fully implements the interface
13 * @see ODateBookAccessBackend
14 * @see OPimAccessBackend
15 */
16class ODateBookAccessBackend_SQL : public ODateBookAccessBackend {
17public:
18 ODateBookAccessBackend_SQL( const QString& appName,
19 const QString& fileName = QString::null);
20 ~ODateBookAccessBackend_SQL();
21
22 bool load();
23 bool reload();
24 bool save();
25
26 QArray<int> allRecords()const;
27 QArray<int> matchRegexp(const QRegExp &r) const;
28 QArray<int> queryByExample( const OEvent&, int, const QDateTime& d = QDateTime() );
29 OEvent find( int uid )const;
30 void clear();
31 bool add( const OEvent& ev );
32 bool remove( int uid );
33 bool replace( const OEvent& ev );
34
35 QArray<UID> rawEvents()const;
36 QArray<UID> rawRepeats()const;
37 QArray<UID> nonRepeats()const;
38
39 OEvent::ValueList directNonRepeats();
40 OEvent::ValueList directRawRepeats();
41
42private:
43 bool loadFile();
44 QString m_fileName;
45 QArray<int> m_uids;
46
47 QMap<int, QString> m_fieldMap;
48
49 OSQLDriver* m_driver;
50
51 class Private;
52 Private *d;
53
54 void initFields();
55 void update();
56 QArray<int> extractUids( OSQLResult& res ) const;
57
58};
59
60#endif
diff --git a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
index 39c43c5..929d004 100644
--- a/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
+++ b/libopie2/opiepim/backend/odatebookaccessbackend_xml.cpp
@@ -1,606 +1,612 @@
1#include <errno.h> 1#include <errno.h>
2#include <fcntl.h> 2#include <fcntl.h>
3 3
4#include <stdio.h> 4#include <stdio.h>
5#include <stdlib.h> 5#include <stdlib.h>
6 6
7#include <sys/types.h> 7#include <sys/types.h>
8#include <sys/mman.h> 8#include <sys/mman.h>
9#include <sys/stat.h> 9#include <sys/stat.h>
10 10
11#include <unistd.h> 11#include <unistd.h>
12 12
13#include <qasciidict.h> 13#include <qasciidict.h>
14#include <qfile.h> 14#include <qfile.h>
15 15
16#include <qtopia/global.h> 16#include <qtopia/global.h>
17#include <qtopia/stringutil.h> 17#include <qtopia/stringutil.h>
18#include <qtopia/timeconversion.h> 18#include <qtopia/timeconversion.h>
19 19
20#include "opimnotifymanager.h" 20#include "opimnotifymanager.h"
21#include "orecur.h" 21#include "orecur.h"
22#include "otimezone.h" 22#include "otimezone.h"
23#include "odatebookaccessbackend_xml.h" 23#include "odatebookaccessbackend_xml.h"
24 24
25namespace { 25namespace {
26 // FROM TT again 26 // FROM TT again
27char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen) 27char *strstrlen(const char *haystack, int hLen, const char* needle, int nLen)
28{ 28{
29 char needleChar; 29 char needleChar;
30 char haystackChar; 30 char haystackChar;
31 if (!needle || !haystack || !hLen || !nLen) 31 if (!needle || !haystack || !hLen || !nLen)
32 return 0; 32 return 0;
33 33
34 const char* hsearch = haystack; 34 const char* hsearch = haystack;
35 35
36 if ((needleChar = *needle++) != 0) { 36 if ((needleChar = *needle++) != 0) {
37 nLen--; //(to make up for needle++) 37 nLen--; //(to make up for needle++)
38 do { 38 do {
39 do { 39 do {
40 if ((haystackChar = *hsearch++) == 0) 40 if ((haystackChar = *hsearch++) == 0)
41 return (0); 41 return (0);
42 if (hsearch >= haystack + hLen) 42 if (hsearch >= haystack + hLen)
43 return (0); 43 return (0);
44 } while (haystackChar != needleChar); 44 } while (haystackChar != needleChar);
45 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0); 45 } while (strncmp(hsearch, needle, QMIN(hLen - (hsearch - haystack), nLen)) != 0);
46 hsearch--; 46 hsearch--;
47 } 47 }
48 return ((char *)hsearch); 48 return ((char *)hsearch);
49} 49}
50} 50}
51 51
52namespace { 52namespace {
53 time_t start, end, created, rp_end; 53 time_t start, end, created, rp_end;
54 ORecur* rec; 54 ORecur* rec;
55 ORecur* recur() { 55 ORecur* recur() {
56 if (!rec) 56 if (!rec)
57 rec = new ORecur; 57 rec = new ORecur;
58 58
59 return rec; 59 return rec;
60 } 60 }
61 int alarmTime; 61 int alarmTime;
62 int snd; 62 int snd;
63 enum Attribute{ 63 enum Attribute{
64 FDescription = 0, 64 FDescription = 0,
65 FLocation, 65 FLocation,
66 FCategories, 66 FCategories,
67 FUid, 67 FUid,
68 FType, 68 FType,
69 FAlarm, 69 FAlarm,
70 FSound, 70 FSound,
71 FRType, 71 FRType,
72 FRWeekdays, 72 FRWeekdays,
73 FRPosition, 73 FRPosition,
74 FRFreq, 74 FRFreq,
75 FRHasEndDate, 75 FRHasEndDate,
76 FREndDate, 76 FREndDate,
77 FRStart, 77 FRStart,
78 FREnd, 78 FREnd,
79 FNote, 79 FNote,
80 FCreated, 80 FCreated, // Should't this be called FRCreated ?
81 FTimeZone, 81 FTimeZone,
82 FRecParent, 82 FRecParent,
83 FRecChildren, 83 FRecChildren,
84 FExceptions 84 FExceptions
85 }; 85 };
86
87 // FIXME: Use OEvent::toMap() here !! (eilers)
86 inline void save( const OEvent& ev, QString& buf ) { 88 inline void save( const OEvent& ev, QString& buf ) {
87 qWarning("Saving %d %s", ev.uid(), ev.description().latin1() ); 89 qWarning("Saving %d %s", ev.uid(), ev.description().latin1() );
88 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\""; 90 buf += " description=\"" + Qtopia::escapeString(ev.description() ) + "\"";
89 if (!ev.location().isEmpty() ) 91 if (!ev.location().isEmpty() )
90 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\""; 92 buf += " location=\"" + Qtopia::escapeString(ev.location() ) + "\"";
91 93
92 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\""; 94 buf += " categories=\""+ Qtopia::escapeString( Qtopia::Record::idsToString( ev.categories() ) ) + "\"";
93 buf += " uid=\"" + QString::number( ev.uid() ) + "\""; 95 buf += " uid=\"" + QString::number( ev.uid() ) + "\"";
94 96
95 if (ev.isAllDay() ) 97 if (ev.isAllDay() )
96 buf += " type=\"AllDay\""; // is that all ?? (eilers) 98 buf += " type=\"AllDay\""; // is that all ?? (eilers)
97 99
98 if (ev.hasNotifiers() ) { 100 if (ev.hasNotifiers() ) {
99 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first 101 OPimAlarm alarm = ev.notifiers().alarms()[0]; // take only the first
100 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60; 102 int minutes = alarm.dateTime().secsTo( ev.startDateTime() ) / 60;
101 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\""; 103 buf += " alarm=\"" + QString::number(minutes) + "\" sound=\"";
102 if ( alarm.sound() == OPimAlarm::Loud ) 104 if ( alarm.sound() == OPimAlarm::Loud )
103 buf += "loud"; 105 buf += "loud";
104 else 106 else
105 buf += "silent"; 107 buf += "silent";
106 buf += "\""; 108 buf += "\"";
107 } 109 }
108 if ( ev.hasRecurrence() ) { 110 if ( ev.hasRecurrence() ) {
109 buf += ev.recurrence().toString(); 111 buf += ev.recurrence().toString();
110 } 112 }
111 113
112 /* 114 /*
113 * fscking timezones :) well, we'll first convert 115 * fscking timezones :) well, we'll first convert
114 * the QDateTime to a QDateTime in UTC time 116 * the QDateTime to a QDateTime in UTC time
115 * and then we'll create a nice time_t 117 * and then we'll create a nice time_t
116 */ 118 */
117 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); 119 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
118 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\""; 120 buf += " start=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.startDateTime(), OTimeZone::utc() ) ) ) + "\"";
119 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\""; 121 buf += " end=\"" + QString::number( zone.fromUTCDateTime( zone.toDateTime( ev.endDateTime() , OTimeZone::utc() ) ) ) + "\"";
120 if (!ev.note().isEmpty() ) { 122 if (!ev.note().isEmpty() ) {
121 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\""; 123 buf += " note=\"" + Qtopia::escapeString( ev.note() ) + "\"";
122 } 124 }
123 125
124 buf += " timezone=\""; 126 buf += " timezone=\"";
125 if ( ev.timeZone().isEmpty() ) 127 if ( ev.timeZone().isEmpty() )
126 buf += "None"; 128 buf += "None";
127 else 129 else
128 buf += ev.timeZone(); 130 buf += ev.timeZone();
129 buf += "\""; 131 buf += "\"";
130 132
131 if (ev.parent() != 0 ) { 133 if (ev.parent() != 0 ) {
132 buf += " recparent=\""+QString::number(ev.parent() )+"\""; 134 buf += " recparent=\""+QString::number(ev.parent() )+"\"";
133 } 135 }
134 136
135 if (ev.children().count() != 0 ) { 137 if (ev.children().count() != 0 ) {
136 QArray<int> children = ev.children(); 138 QArray<int> children = ev.children();
137 buf += " recchildren=\""; 139 buf += " recchildren=\"";
138 for ( uint i = 0; i < children.count(); i++ ) { 140 for ( uint i = 0; i < children.count(); i++ ) {
139 if ( i != 0 ) buf += " "; 141 if ( i != 0 ) buf += " ";
140 buf += QString::number( children[i] ); 142 buf += QString::number( children[i] );
141 } 143 }
142 buf+= "\""; 144 buf+= "\"";
143 } 145 }
144 146
145 // skip custom writing 147 // skip custom writing
146 } 148 }
147 149
148 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) { 150 inline bool forAll( const QMap<int, OEvent>& list, QFile& file ) {
149 QMap<int, OEvent>::ConstIterator it; 151 QMap<int, OEvent>::ConstIterator it;
150 QString buf; 152 QString buf;
151 QCString str; 153 QCString str;
152 int total_written; 154 int total_written;
153 for ( it = list.begin(); it != list.end(); ++it ) { 155 for ( it = list.begin(); it != list.end(); ++it ) {
154 buf = "<event"; 156 buf = "<event";
155 save( it.data(), buf ); 157 save( it.data(), buf );
156 buf += " />\n"; 158 buf += " />\n";
157 str = buf.utf8(); 159 str = buf.utf8();
158 160
159 total_written = file.writeBlock(str.data(), str.length() ); 161 total_written = file.writeBlock(str.data(), str.length() );
160 if ( total_written != int(str.length() ) ) 162 if ( total_written != int(str.length() ) )
161 return false; 163 return false;
162 } 164 }
163 return true; 165 return true;
164 } 166 }
165} 167}
166 168
167ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& , 169ODateBookAccessBackend_XML::ODateBookAccessBackend_XML( const QString& ,
168 const QString& fileName ) 170 const QString& fileName )
169 : ODateBookAccessBackend() { 171 : ODateBookAccessBackend() {
170 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName; 172 m_name = fileName.isEmpty() ? Global::applicationFileName( "datebook", "datebook.xml" ) : fileName;
171 m_changed = false; 173 m_changed = false;
172} 174}
173ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() { 175ODateBookAccessBackend_XML::~ODateBookAccessBackend_XML() {
174} 176}
175bool ODateBookAccessBackend_XML::load() { 177bool ODateBookAccessBackend_XML::load() {
176 return loadFile(); 178 return loadFile();
177} 179}
178bool ODateBookAccessBackend_XML::reload() { 180bool ODateBookAccessBackend_XML::reload() {
179 clear(); 181 clear();
180 return load(); 182 return load();
181} 183}
182bool ODateBookAccessBackend_XML::save() { 184bool ODateBookAccessBackend_XML::save() {
183 if (!m_changed) return true; 185 if (!m_changed) return true;
184 186
185 int total_written; 187 int total_written;
186 QString strFileNew = m_name + ".new"; 188 QString strFileNew = m_name + ".new";
187 189
188 QFile f( strFileNew ); 190 QFile f( strFileNew );
189 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false; 191 if (!f.open( IO_WriteOnly | IO_Raw ) ) return false;
190 192
191 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ); 193 QString buf( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" );
192 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n"; 194 buf += "<!DOCTYPE DATEBOOK><DATEBOOK>\n";
193 buf += "<events>\n"; 195 buf += "<events>\n";
194 QCString str = buf.utf8(); 196 QCString str = buf.utf8();
195 total_written = f.writeBlock( str.data(), str.length() ); 197 total_written = f.writeBlock( str.data(), str.length() );
196 if ( total_written != int(str.length() ) ) { 198 if ( total_written != int(str.length() ) ) {
197 f.close(); 199 f.close();
198 QFile::remove( strFileNew ); 200 QFile::remove( strFileNew );
199 return false; 201 return false;
200 } 202 }
201 203
202 if (!forAll( m_raw, f ) ) { 204 if (!forAll( m_raw, f ) ) {
203 f.close(); 205 f.close();
204 QFile::remove( strFileNew ); 206 QFile::remove( strFileNew );
205 return false; 207 return false;
206 } 208 }
207 if (!forAll( m_rep, f ) ) { 209 if (!forAll( m_rep, f ) ) {
208 f.close(); 210 f.close();
209 QFile::remove( strFileNew ); 211 QFile::remove( strFileNew );
210 return false; 212 return false;
211 } 213 }
212 214
213 buf = "</events>\n</DATEBOOK>\n"; 215 buf = "</events>\n</DATEBOOK>\n";
214 str = buf.utf8(); 216 str = buf.utf8();
215 total_written = f.writeBlock( str.data(), str.length() ); 217 total_written = f.writeBlock( str.data(), str.length() );
216 if ( total_written != int(str.length() ) ) { 218 if ( total_written != int(str.length() ) ) {
217 f.close(); 219 f.close();
218 QFile::remove( strFileNew ); 220 QFile::remove( strFileNew );
219 return false; 221 return false;
220 } 222 }
221 f.close(); 223 f.close();
222 224
223 if ( ::rename( strFileNew, m_name ) < 0 ) { 225 if ( ::rename( strFileNew, m_name ) < 0 ) {
224 QFile::remove( strFileNew ); 226 QFile::remove( strFileNew );
225 return false; 227 return false;
226 } 228 }
227 229
228 m_changed = false; 230 m_changed = false;
229 return true; 231 return true;
230} 232}
231QArray<int> ODateBookAccessBackend_XML::allRecords()const { 233QArray<int> ODateBookAccessBackend_XML::allRecords()const {
232 QArray<int> ints( m_raw.count()+ m_rep.count() ); 234 QArray<int> ints( m_raw.count()+ m_rep.count() );
233 uint i = 0; 235 uint i = 0;
234 QMap<int, OEvent>::ConstIterator it; 236 QMap<int, OEvent>::ConstIterator it;
235 237
236 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 238 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
237 ints[i] = it.key(); 239 ints[i] = it.key();
238 i++; 240 i++;
239 } 241 }
240 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 242 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
241 ints[i] = it.key(); 243 ints[i] = it.key();
242 i++; 244 i++;
243 } 245 }
244 246
245 return ints; 247 return ints;
246} 248}
247QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) { 249QArray<int> ODateBookAccessBackend_XML::queryByExample(const OEvent&, int, const QDateTime& ) {
248 return QArray<int>(); 250 return QArray<int>();
249} 251}
250void ODateBookAccessBackend_XML::clear() { 252void ODateBookAccessBackend_XML::clear() {
251 m_changed = true; 253 m_changed = true;
252 m_raw.clear(); 254 m_raw.clear();
253 m_rep.clear(); 255 m_rep.clear();
254} 256}
255OEvent ODateBookAccessBackend_XML::find( int uid ) const{ 257OEvent ODateBookAccessBackend_XML::find( int uid ) const{
256 if ( m_raw.contains( uid ) ) 258 if ( m_raw.contains( uid ) )
257 return m_raw[uid]; 259 return m_raw[uid];
258 else 260 else
259 return m_rep[uid]; 261 return m_rep[uid];
260} 262}
261bool ODateBookAccessBackend_XML::add( const OEvent& ev ) { 263bool ODateBookAccessBackend_XML::add( const OEvent& ev ) {
262 m_changed = true; 264 m_changed = true;
263 if (ev.hasRecurrence() ) 265 if (ev.hasRecurrence() )
264 m_rep.insert( ev.uid(), ev ); 266 m_rep.insert( ev.uid(), ev );
265 else 267 else
266 m_raw.insert( ev.uid(), ev ); 268 m_raw.insert( ev.uid(), ev );
267 269
268 return true; 270 return true;
269} 271}
270bool ODateBookAccessBackend_XML::remove( int uid ) { 272bool ODateBookAccessBackend_XML::remove( int uid ) {
271 m_changed = true; 273 m_changed = true;
272 m_rep.remove( uid ); 274 m_rep.remove( uid );
273 m_rep.remove( uid ); 275 m_rep.remove( uid );
274 276
275 return true; 277 return true;
276} 278}
277bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) { 279bool ODateBookAccessBackend_XML::replace( const OEvent& ev ) {
278 replace( ev.uid() ); 280 replace( ev.uid() ); // ??? Shouldn't this be "remove( ev.uid() ) ??? (eilers)
279 return add( ev ); 281 return add( ev );
280} 282}
281QArray<int> ODateBookAccessBackend_XML::rawEvents()const { 283QArray<int> ODateBookAccessBackend_XML::rawEvents()const {
282 return allRecords(); 284 return allRecords();
283} 285}
284QArray<int> ODateBookAccessBackend_XML::rawRepeats()const { 286QArray<int> ODateBookAccessBackend_XML::rawRepeats()const {
285 QArray<int> ints( m_rep.count() ); 287 QArray<int> ints( m_rep.count() );
286 uint i = 0; 288 uint i = 0;
287 QMap<int, OEvent>::ConstIterator it; 289 QMap<int, OEvent>::ConstIterator it;
288 290
289 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) { 291 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) {
290 ints[i] = it.key(); 292 ints[i] = it.key();
291 i++; 293 i++;
292 } 294 }
293 295
294 return ints; 296 return ints;
295} 297}
296QArray<int> ODateBookAccessBackend_XML::nonRepeats()const { 298QArray<int> ODateBookAccessBackend_XML::nonRepeats()const {
297 QArray<int> ints( m_raw.count() ); 299 QArray<int> ints( m_raw.count() );
298 uint i = 0; 300 uint i = 0;
299 QMap<int, OEvent>::ConstIterator it; 301 QMap<int, OEvent>::ConstIterator it;
300 302
301 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) { 303 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) {
302 ints[i] = it.key(); 304 ints[i] = it.key();
303 i++; 305 i++;
304 } 306 }
305 307
306 return ints; 308 return ints;
307} 309}
308OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() { 310OEvent::ValueList ODateBookAccessBackend_XML::directNonRepeats() {
309 OEvent::ValueList list; 311 OEvent::ValueList list;
310 QMap<int, OEvent>::ConstIterator it; 312 QMap<int, OEvent>::ConstIterator it;
311 for (it = m_raw.begin(); it != m_raw.end(); ++it ) 313 for (it = m_raw.begin(); it != m_raw.end(); ++it )
312 list.append( it.data() ); 314 list.append( it.data() );
313 315
314 return list; 316 return list;
315} 317}
316OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() { 318OEvent::ValueList ODateBookAccessBackend_XML::directRawRepeats() {
317 OEvent::ValueList list; 319 OEvent::ValueList list;
318 QMap<int, OEvent>::ConstIterator it; 320 QMap<int, OEvent>::ConstIterator it;
319 for (it = m_rep.begin(); it != m_rep.end(); ++it ) 321 for (it = m_rep.begin(); it != m_rep.end(); ++it )
320 list.append( it.data() ); 322 list.append( it.data() );
321 323
322 return list; 324 return list;
323} 325}
326
327// FIXME: Use OEvent::fromMap() (eilers)
324bool ODateBookAccessBackend_XML::loadFile() { 328bool ODateBookAccessBackend_XML::loadFile() {
325 m_changed = false; 329 m_changed = false;
326 330
327 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY ); 331 int fd = ::open( QFile::encodeName(m_name).data(), O_RDONLY );
328 if ( fd < 0 ) return false; 332 if ( fd < 0 ) return false;
329 333
330 struct stat attribute; 334 struct stat attribute;
331 if ( ::fstat(fd, &attribute ) == -1 ) { 335 if ( ::fstat(fd, &attribute ) == -1 ) {
332 ::close( fd ); 336 ::close( fd );
333 return false; 337 return false;
334 } 338 }
335 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 ); 339 void* map_addr = ::mmap(NULL, attribute.st_size, PROT_READ, MAP_SHARED, fd, 0 );
336 if ( map_addr == ( (caddr_t)-1) ) { 340 if ( map_addr == ( (caddr_t)-1) ) {
337 ::close( fd ); 341 ::close( fd );
338 return false; 342 return false;
339 } 343 }
340 344
341 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL ); 345 ::madvise( map_addr, attribute.st_size, MADV_SEQUENTIAL );
342 ::close( fd ); 346 ::close( fd );
343 347
344 QAsciiDict<int> dict(FExceptions+1); 348 QAsciiDict<int> dict(FExceptions+1);
345 dict.setAutoDelete( true ); 349 dict.setAutoDelete( true );
346 dict.insert( "description", new int(FDescription) ); 350 dict.insert( "description", new int(FDescription) );
347 dict.insert( "location", new int(FLocation) ); 351 dict.insert( "location", new int(FLocation) );
348 dict.insert( "categories", new int(FCategories) ); 352 dict.insert( "categories", new int(FCategories) );
349 dict.insert( "uid", new int(FUid) ); 353 dict.insert( "uid", new int(FUid) );
350 dict.insert( "type", new int(FType) ); 354 dict.insert( "type", new int(FType) );
351 dict.insert( "alarm", new int(FAlarm) ); 355 dict.insert( "alarm", new int(FAlarm) );
352 dict.insert( "sound", new int(FSound) ); 356 dict.insert( "sound", new int(FSound) );
353 dict.insert( "rtype", new int(FRType) ); 357 dict.insert( "rtype", new int(FRType) );
354 dict.insert( "rweekdays", new int(FRWeekdays) ); 358 dict.insert( "rweekdays", new int(FRWeekdays) );
355 dict.insert( "rposition", new int(FRPosition) ); 359 dict.insert( "rposition", new int(FRPosition) );
356 dict.insert( "rfreq", new int(FRFreq) ); 360 dict.insert( "rfreq", new int(FRFreq) );
357 dict.insert( "rhasenddate", new int(FRHasEndDate) ); 361 dict.insert( "rhasenddate", new int(FRHasEndDate) );
358 dict.insert( "enddt", new int(FREndDate) ); 362 dict.insert( "enddt", new int(FREndDate) );
359 dict.insert( "start", new int(FRStart) ); 363 dict.insert( "start", new int(FRStart) );
360 dict.insert( "end", new int(FREnd) ); 364 dict.insert( "end", new int(FREnd) );
361 dict.insert( "note", new int(FNote) ); 365 dict.insert( "note", new int(FNote) );
362 dict.insert( "created", new int(FCreated) ); 366 dict.insert( "created", new int(FCreated) ); // Shouldn't this be FRCreated ??
363 dict.insert( "recparent", new int(FRecParent) ); 367 dict.insert( "recparent", new int(FRecParent) );
364 dict.insert( "recchildren", new int(FRecChildren) ); 368 dict.insert( "recchildren", new int(FRecChildren) );
365 dict.insert( "exceptions", new int(FExceptions) ); 369 dict.insert( "exceptions", new int(FExceptions) );
366 dict.insert( "timezone", new int(FTimeZone) ); 370 dict.insert( "timezone", new int(FTimeZone) );
367 371
368 char* dt = (char*)map_addr; 372 char* dt = (char*)map_addr;
369 int len = attribute.st_size; 373 int len = attribute.st_size;
370 int i = 0; 374 int i = 0;
371 char* point; 375 char* point;
372 const char* collectionString = "<event "; 376 const char* collectionString = "<event ";
373 int strLen = ::strlen(collectionString); 377 int strLen = ::strlen(collectionString);
374 int *find; 378 int *find;
375 while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) { 379 while ( ( point = ::strstrlen( dt+i, len -i, collectionString, strLen ) ) != 0 ) {
376 i = point -dt; 380 i = point -dt;
377 i+= strLen; 381 i+= strLen;
378 382
379 alarmTime = -1; 383 alarmTime = -1;
380 snd = 0; // silent 384 snd = 0; // silent
381 385
382 OEvent ev; 386 OEvent ev;
383 rec = 0; 387 rec = 0;
384 388
385 while ( TRUE ) { 389 while ( TRUE ) {
386 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') ) 390 while ( i < len && (dt[i] == ' ' || dt[i] == '\n' || dt[i] == '\r') )
387 ++i; 391 ++i;
388 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') ) 392 if ( i >= len-2 || (dt[i] == '/' && dt[i+1] == '>') )
389 break; 393 break;
390 394
391 395
392 // we have another attribute, read it. 396 // we have another attribute, read it.
393 int j = i; 397 int j = i;
394 while ( j < len && dt[j] != '=' ) 398 while ( j < len && dt[j] != '=' )
395 ++j; 399 ++j;
396 QCString attr( dt+i, j-i+1); 400 QCString attr( dt+i, j-i+1);
397 401
398 i = ++j; // skip = 402 i = ++j; // skip =
399 403
400 // find the start of quotes 404 // find the start of quotes
401 while ( i < len && dt[i] != '"' ) 405 while ( i < len && dt[i] != '"' )
402 ++i; 406 ++i;
403 j = ++i; 407 j = ++i;
404 408
405 bool haveUtf = FALSE; 409 bool haveUtf = FALSE;
406 bool haveEnt = FALSE; 410 bool haveEnt = FALSE;
407 while ( j < len && dt[j] != '"' ) { 411 while ( j < len && dt[j] != '"' ) {
408 if ( ((unsigned char)dt[j]) > 0x7f ) 412 if ( ((unsigned char)dt[j]) > 0x7f )
409 haveUtf = TRUE; 413 haveUtf = TRUE;
410 if ( dt[j] == '&' ) 414 if ( dt[j] == '&' )
411 haveEnt = TRUE; 415 haveEnt = TRUE;
412 ++j; 416 ++j;
413 } 417 }
414 if ( i == j ) { 418 if ( i == j ) {
415 // empty value 419 // empty value
416 i = j + 1; 420 i = j + 1;
417 continue; 421 continue;
418 } 422 }
419 423
420 QCString value( dt+i, j-i+1 ); 424 QCString value( dt+i, j-i+1 );
421 i = j + 1; 425 i = j + 1;
422 426
423 QString str = (haveUtf ? QString::fromUtf8( value ) 427 QString str = (haveUtf ? QString::fromUtf8( value )
424 : QString::fromLatin1( value ) ); 428 : QString::fromLatin1( value ) );
425 if ( haveEnt ) 429 if ( haveEnt )
426 str = Qtopia::plainString( str ); 430 str = Qtopia::plainString( str );
427 431
428 /* 432 /*
429 * add key + value 433 * add key + value
430 */ 434 */
431 find = dict[attr.data()]; 435 find = dict[attr.data()];
432 if (!find) 436 if (!find)
433 ev.setCustomField( attr, str ); 437 ev.setCustomField( attr, str );
434 else { 438 else {
435 setField( ev, *find, str ); 439 setField( ev, *find, str );
436 } 440 }
437 } 441 }
438 /* time to finalize */ 442 /* time to finalize */
439 finalizeRecord( ev ); 443 finalizeRecord( ev );
440 delete rec; 444 delete rec;
441 } 445 }
442 ::munmap(map_addr, attribute.st_size ); 446 ::munmap(map_addr, attribute.st_size );
443 m_changed = false; // changed during add 447 m_changed = false; // changed during add
444 448
445 return true; 449 return true;
446} 450}
451
452// FIXME: Use OEvent::fromMap() which makes this obsolete.. (eilers)
447void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) { 453void ODateBookAccessBackend_XML::finalizeRecord( OEvent& ev ) {
448 /* AllDay is alway in UTC */ 454 /* AllDay is alway in UTC */
449 if ( ev.isAllDay() ) { 455 if ( ev.isAllDay() ) {
450 OTimeZone utc = OTimeZone::utc(); 456 OTimeZone utc = OTimeZone::utc();
451 ev.setStartDateTime( utc.fromUTCDateTime( start ) ); 457 ev.setStartDateTime( utc.fromUTCDateTime( start ) );
452 ev.setEndDateTime ( utc.fromUTCDateTime( end ) ); 458 ev.setEndDateTime ( utc.fromUTCDateTime( end ) );
453 ev.setTimeZone( "UTC"); // make sure it is really utc 459 ev.setTimeZone( "UTC"); // make sure it is really utc
454 }else { 460 }else {
455 /* to current date time */ 461 /* to current date time */
456 // qWarning(" Start is %d", start ); 462 // qWarning(" Start is %d", start );
457 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() ); 463 OTimeZone zone( ev.timeZone().isEmpty() ? OTimeZone::current() : ev.timeZone() );
458 QDateTime date = zone.toDateTime( start ); 464 QDateTime date = zone.toDateTime( start );
459 qWarning(" Start is %s", date.toString().latin1() ); 465 qWarning(" Start is %s", date.toString().latin1() );
460 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) ); 466 ev.setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
461 467
462 date = zone.toDateTime( end ); 468 date = zone.toDateTime( end );
463 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) ); 469 ev.setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
464 } 470 }
465 if ( rec && rec->doesRecur() ) { 471 if ( rec && rec->doesRecur() ) {
466 OTimeZone utc = OTimeZone::utc(); 472 OTimeZone utc = OTimeZone::utc();
467 ORecur recu( *rec ); // call copy c'tor; 473 ORecur recu( *rec ); // call copy c'tor;
468 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() ); 474 recu.setEndDate ( utc.fromUTCDateTime( rp_end ).date() );
469 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) ); 475 recu.setCreatedDateTime( utc.fromUTCDateTime( created ) );
470 recu.setStart( ev.startDateTime().date() ); 476 recu.setStart( ev.startDateTime().date() );
471 ev.setRecurrence( recu ); 477 ev.setRecurrence( recu );
472 } 478 }
473 479
474 if (alarmTime != -1 ) { 480 if (alarmTime != -1 ) {
475 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 ); 481 QDateTime dt = ev.startDateTime().addSecs( -1*alarmTime*60 );
476 OPimAlarm al( snd , dt ); 482 OPimAlarm al( snd , dt );
477 ev.notifiers().add( al ); 483 ev.notifiers().add( al );
478 } 484 }
479 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) { 485 if ( m_raw.contains( ev.uid() ) || m_rep.contains( ev.uid() ) ) {
480 qWarning("already contains assign uid"); 486 qWarning("already contains assign uid");
481 ev.setUid( 1 ); 487 ev.setUid( 1 );
482 } 488 }
483 qWarning("addind %d %s", ev.uid(), ev.description().latin1() ); 489 qWarning("addind %d %s", ev.uid(), ev.description().latin1() );
484 if ( ev.hasRecurrence() ) 490 if ( ev.hasRecurrence() )
485 m_rep.insert( ev.uid(), ev ); 491 m_rep.insert( ev.uid(), ev );
486 else 492 else
487 m_raw.insert( ev.uid(), ev ); 493 m_raw.insert( ev.uid(), ev );
488 494
489} 495}
490void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) { 496void ODateBookAccessBackend_XML::setField( OEvent& e, int id, const QString& value) {
491// qWarning(" setting %s", value.latin1() ); 497// qWarning(" setting %s", value.latin1() );
492 switch( id ) { 498 switch( id ) {
493 case FDescription: 499 case FDescription:
494 e.setDescription( value ); 500 e.setDescription( value );
495 break; 501 break;
496 case FLocation: 502 case FLocation:
497 e.setLocation( value ); 503 e.setLocation( value );
498 break; 504 break;
499 case FCategories: 505 case FCategories:
500 e.setCategories( e.idsFromString( value ) ); 506 e.setCategories( e.idsFromString( value ) );
501 break; 507 break;
502 case FUid: 508 case FUid:
503 e.setUid( value.toInt() ); 509 e.setUid( value.toInt() );
504 break; 510 break;
505 case FType: 511 case FType:
506 if ( value == "AllDay" ) { 512 if ( value == "AllDay" ) {
507 e.setAllDay( true ); 513 e.setAllDay( true );
508 e.setTimeZone( "UTC" ); 514 e.setTimeZone( "UTC" );
509 } 515 }
510 break; 516 break;
511 case FAlarm: 517 case FAlarm:
512 alarmTime = value.toInt(); 518 alarmTime = value.toInt();
513 break; 519 break;
514 case FSound: 520 case FSound:
515 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent; 521 snd = value == "loud" ? OPimAlarm::Loud : OPimAlarm::Silent;
516 break; 522 break;
517 // recurrence stuff 523 // recurrence stuff
518 case FRType: 524 case FRType:
519 if ( value == "Daily" ) 525 if ( value == "Daily" )
520 recur()->setType( ORecur::Daily ); 526 recur()->setType( ORecur::Daily );
521 else if ( value == "Weekly" ) 527 else if ( value == "Weekly" )
522 recur()->setType( ORecur::Weekly); 528 recur()->setType( ORecur::Weekly);
523 else if ( value == "MonthlyDay" ) 529 else if ( value == "MonthlyDay" )
524 recur()->setType( ORecur::MonthlyDay ); 530 recur()->setType( ORecur::MonthlyDay );
525 else if ( value == "MonthlyDate" ) 531 else if ( value == "MonthlyDate" )
526 recur()->setType( ORecur::MonthlyDate ); 532 recur()->setType( ORecur::MonthlyDate );
527 else if ( value == "Yearly" ) 533 else if ( value == "Yearly" )
528 recur()->setType( ORecur::Yearly ); 534 recur()->setType( ORecur::Yearly );
529 else 535 else
530 recur()->setType( ORecur::NoRepeat ); 536 recur()->setType( ORecur::NoRepeat );
531 break; 537 break;
532 case FRWeekdays: 538 case FRWeekdays:
533 recur()->setDays( value.toInt() ); 539 recur()->setDays( value.toInt() );
534 break; 540 break;
535 case FRPosition: 541 case FRPosition:
536 recur()->setPosition( value.toInt() ); 542 recur()->setPosition( value.toInt() );
537 break; 543 break;
538 case FRFreq: 544 case FRFreq:
539 recur()->setFrequency( value.toInt() ); 545 recur()->setFrequency( value.toInt() );
540 break; 546 break;
541 case FRHasEndDate: 547 case FRHasEndDate:
542 recur()->setHasEndDate( value.toInt() ); 548 recur()->setHasEndDate( value.toInt() );
543 break; 549 break;
544 case FREndDate: { 550 case FREndDate: {
545 rp_end = (time_t) value.toLong(); 551 rp_end = (time_t) value.toLong();
546 break; 552 break;
547 } 553 }
548 case FRStart: { 554 case FRStart: {
549 start = (time_t) value.toLong(); 555 start = (time_t) value.toLong();
550 break; 556 break;
551 } 557 }
552 case FREnd: { 558 case FREnd: {
553 end = ( (time_t) value.toLong() ); 559 end = ( (time_t) value.toLong() );
554 break; 560 break;
555 } 561 }
556 case FNote: 562 case FNote:
557 e.setNote( value ); 563 e.setNote( value );
558 break; 564 break;
559 case FCreated: 565 case FCreated:
560 created = value.toInt(); 566 created = value.toInt();
561 break; 567 break;
562 case FRecParent: 568 case FRecParent:
563 e.setParent( value.toInt() ); 569 e.setParent( value.toInt() );
564 break; 570 break;
565 case FRecChildren:{ 571 case FRecChildren:{
566 QStringList list = QStringList::split(' ', value ); 572 QStringList list = QStringList::split(' ', value );
567 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { 573 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
568 e.addChild( (*it).toInt() ); 574 e.addChild( (*it).toInt() );
569 } 575 }
570 } 576 }
571 break; 577 break;
572 case FExceptions:{ 578 case FExceptions:{
573 QStringList list = QStringList::split(' ', value ); 579 QStringList list = QStringList::split(' ', value );
574 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { 580 for (QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
575 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() ); 581 QDate date( (*it).left(4).toInt(), (*it).mid(4, 2).toInt(), (*it).right(2).toInt() );
576 qWarning("adding exception %s", date.toString().latin1() ); 582 qWarning("adding exception %s", date.toString().latin1() );
577 recur()->exceptions().append( date ); 583 recur()->exceptions().append( date );
578 } 584 }
579 } 585 }
580 break; 586 break;
581 case FTimeZone: 587 case FTimeZone:
582 if ( value != "None" ) 588 if ( value != "None" )
583 e.setTimeZone( value ); 589 e.setTimeZone( value );
584 break; 590 break;
585 default: 591 default:
586 break; 592 break;
587 } 593 }
588} 594}
589QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const 595QArray<int> ODateBookAccessBackend_XML::matchRegexp( const QRegExp &r ) const
590{ 596{
591 QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() ); 597 QArray<int> m_currentQuery( m_raw.count()+ m_rep.count() );
592 uint arraycounter = 0; 598 uint arraycounter = 0;
593 QMap<int, OEvent>::ConstIterator it; 599 QMap<int, OEvent>::ConstIterator it;
594 600
595 for ( it = m_raw.begin(); it != m_raw.end(); ++it ) 601 for ( it = m_raw.begin(); it != m_raw.end(); ++it )
596 if ( it.data().match( r ) ) 602 if ( it.data().match( r ) )
597 m_currentQuery[arraycounter++] = it.data().uid(); 603 m_currentQuery[arraycounter++] = it.data().uid();
598 for ( it = m_rep.begin(); it != m_rep.end(); ++it ) 604 for ( it = m_rep.begin(); it != m_rep.end(); ++it )
599 if ( it.data().match( r ) ) 605 if ( it.data().match( r ) )
600 m_currentQuery[arraycounter++] = it.data().uid(); 606 m_currentQuery[arraycounter++] = it.data().uid();
601 607
602 // Shrink to fit.. 608 // Shrink to fit..
603 m_currentQuery.resize(arraycounter); 609 m_currentQuery.resize(arraycounter);
604 610
605 return m_currentQuery; 611 return m_currentQuery;
606} 612}
diff --git a/libopie2/opiepim/backend/otodoaccesssql.cpp b/libopie2/opiepim/backend/otodoaccesssql.cpp
index 3913661..75a0860 100644
--- a/libopie2/opiepim/backend/otodoaccesssql.cpp
+++ b/libopie2/opiepim/backend/otodoaccesssql.cpp
@@ -46,525 +46,528 @@ namespace {
46 /** 46 /**
47 * inserts/adds a OTodo to the table 47 * inserts/adds a OTodo to the table
48 */ 48 */
49 class InsertQuery : public OSQLQuery { 49 class InsertQuery : public OSQLQuery {
50 public: 50 public:
51 InsertQuery(const OTodo& ); 51 InsertQuery(const OTodo& );
52 ~InsertQuery(); 52 ~InsertQuery();
53 QString query()const; 53 QString query()const;
54 private: 54 private:
55 OTodo m_todo; 55 OTodo m_todo;
56 }; 56 };
57 57
58 /** 58 /**
59 * removes one from the table 59 * removes one from the table
60 */ 60 */
61 class RemoveQuery : public OSQLQuery { 61 class RemoveQuery : public OSQLQuery {
62 public: 62 public:
63 RemoveQuery(int uid ); 63 RemoveQuery(int uid );
64 ~RemoveQuery(); 64 ~RemoveQuery();
65 QString query()const; 65 QString query()const;
66 private: 66 private:
67 int m_uid; 67 int m_uid;
68 }; 68 };
69 69
70 /** 70 /**
71 * Clears (delete) a Table 71 * Clears (delete) a Table
72 */ 72 */
73 class ClearQuery : public OSQLQuery { 73 class ClearQuery : public OSQLQuery {
74 public: 74 public:
75 ClearQuery(); 75 ClearQuery();
76 ~ClearQuery(); 76 ~ClearQuery();
77 QString query()const; 77 QString query()const;
78 78
79 }; 79 };
80 80
81 /** 81 /**
82 * a find query 82 * a find query
83 */ 83 */
84 class FindQuery : public OSQLQuery { 84 class FindQuery : public OSQLQuery {
85 public: 85 public:
86 FindQuery(int uid); 86 FindQuery(int uid);
87 FindQuery(const QArray<int>& ); 87 FindQuery(const QArray<int>& );
88 ~FindQuery(); 88 ~FindQuery();
89 QString query()const; 89 QString query()const;
90 private: 90 private:
91 QString single()const; 91 QString single()const;
92 QString multi()const; 92 QString multi()const;
93 QArray<int> m_uids; 93 QArray<int> m_uids;
94 int m_uid; 94 int m_uid;
95 }; 95 };
96 96
97 /** 97 /**
98 * overdue query 98 * overdue query
99 */ 99 */
100 class OverDueQuery : public OSQLQuery { 100 class OverDueQuery : public OSQLQuery {
101 public: 101 public:
102 OverDueQuery(); 102 OverDueQuery();
103 ~OverDueQuery(); 103 ~OverDueQuery();
104 QString query()const; 104 QString query()const;
105 }; 105 };
106 class EffQuery : public OSQLQuery { 106 class EffQuery : public OSQLQuery {
107 public: 107 public:
108 EffQuery( const QDate&, const QDate&, bool inc ); 108 EffQuery( const QDate&, const QDate&, bool inc );
109 ~EffQuery(); 109 ~EffQuery();
110 QString query()const; 110 QString query()const;
111 private: 111 private:
112 QString with()const; 112 QString with()const;
113 QString out()const; 113 QString out()const;
114 QDate m_start; 114 QDate m_start;
115 QDate m_end; 115 QDate m_end;
116 bool m_inc :1; 116 bool m_inc :1;
117 }; 117 };
118 118
119 119
120 CreateQuery::CreateQuery() : OSQLQuery() {} 120 CreateQuery::CreateQuery() : OSQLQuery() {}
121 CreateQuery::~CreateQuery() {} 121 CreateQuery::~CreateQuery() {}
122 QString CreateQuery::query()const { 122 QString CreateQuery::query()const {
123 QString qu; 123 QString qu;
124 qu += "create table todolist( uid PRIMARY KEY, categories, completed, "; 124 qu += "create table todolist( uid PRIMARY KEY, categories, completed, ";
125 qu += "description, summary, priority, DueDate, progress , state, "; 125 qu += "description, summary, priority, DueDate, progress , state, ";
126 // This is the recurrance-stuff .. Exceptions are currently not supported (see ORecur.cpp) ! (eilers) 126 // This is the recurrance-stuff .. Exceptions are currently not supported (see ORecur.cpp) ! (eilers)
127 qu += "RType, RWeekdays, RPosition, RFreq, RHasEndDate, EndDate, Created, Exceptions, "; 127 qu += "RType, RWeekdays, RPosition, RFreq, RHasEndDate, EndDate, Created, Exceptions, ";
128 qu += "reminders, alarms, maintainer, startdate, completeddate);"; 128 qu += "reminders, alarms, maintainer, startdate, completeddate);";
129 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );"; 129 qu += "create table custom_data( uid INTEGER, id INTEGER, type VARCHAR(10), value VARCHAR(10), PRIMARY KEY /* identifier */ (uid, id) );";
130 return qu; 130 return qu;
131 } 131 }
132 132
133 LoadQuery::LoadQuery() : OSQLQuery() {} 133 LoadQuery::LoadQuery() : OSQLQuery() {}
134 LoadQuery::~LoadQuery() {} 134 LoadQuery::~LoadQuery() {}
135 QString LoadQuery::query()const { 135 QString LoadQuery::query()const {
136 QString qu; 136 QString qu;
137 // We do not need "distinct" here. The primary key is always unique.. 137 // We do not need "distinct" here. The primary key is always unique..
138 //qu += "select distinct uid from todolist"; 138 //qu += "select distinct uid from todolist";
139 qu += "select uid from todolist"; 139 qu += "select uid from todolist";
140 140
141 return qu; 141 return qu;
142 } 142 }
143 143
144 InsertQuery::InsertQuery( const OTodo& todo ) 144 InsertQuery::InsertQuery( const OTodo& todo )
145 : OSQLQuery(), m_todo( todo ) { 145 : OSQLQuery(), m_todo( todo ) {
146 } 146 }
147 InsertQuery::~InsertQuery() { 147 InsertQuery::~InsertQuery() {
148 } 148 }
149 /* 149 /*
150 * converts from a OTodo to a query 150 * converts from a OTodo to a query
151 * we leave out X-Ref + Alarms 151 * we leave out X-Ref + Alarms
152 */ 152 */
153 QString InsertQuery::query()const{ 153 QString InsertQuery::query()const{
154 154
155 int year, month, day; 155 int year, month, day;
156 year = month = day = 0; 156 year = month = day = 0;
157 if (m_todo.hasDueDate() ) { 157 if (m_todo.hasDueDate() ) {
158 QDate date = m_todo.dueDate(); 158 QDate date = m_todo.dueDate();
159 year = date.year(); 159 year = date.year();
160 month = date.month(); 160 month = date.month();
161 day = date.day(); 161 day = date.day();
162 } 162 }
163 int sYear = 0, sMonth = 0, sDay = 0; 163 int sYear = 0, sMonth = 0, sDay = 0;
164 if( m_todo.hasStartDate() ){ 164 if( m_todo.hasStartDate() ){
165 QDate sDate = m_todo.startDate(); 165 QDate sDate = m_todo.startDate();
166 sYear = sDate.year(); 166 sYear = sDate.year();
167 sMonth= sDate.month(); 167 sMonth= sDate.month();
168 sDay = sDate.day(); 168 sDay = sDate.day();
169 } 169 }
170 170
171 int eYear = 0, eMonth = 0, eDay = 0; 171 int eYear = 0, eMonth = 0, eDay = 0;
172 if( m_todo.hasCompletedDate() ){ 172 if( m_todo.hasCompletedDate() ){
173 QDate eDate = m_todo.completedDate(); 173 QDate eDate = m_todo.completedDate();
174 eYear = eDate.year(); 174 eYear = eDate.year();
175 eMonth= eDate.month(); 175 eMonth= eDate.month();
176 eDay = eDate.day(); 176 eDay = eDate.day();
177 } 177 }
178 QString qu; 178 QString qu;
179 QMap<int, QString> recMap = m_todo.recurrence().toMap(); 179 QMap<int, QString> recMap = m_todo.recurrence().toMap();
180 qu = "insert into todolist VALUES(" 180 qu = "insert into todolist VALUES("
181 + QString::number( m_todo.uid() ) + "," 181 + QString::number( m_todo.uid() ) + ","
182 + "'" + m_todo.idsToString( m_todo.categories() ) + "'" + "," 182 + "'" + m_todo.idsToString( m_todo.categories() ) + "'" + ","
183 + QString::number( m_todo.isCompleted() ) + "," 183 + QString::number( m_todo.isCompleted() ) + ","
184 + "'" + m_todo.description() + "'" + "," 184 + "'" + m_todo.description() + "'" + ","
185 + "'" + m_todo.summary() + "'" + "," 185 + "'" + m_todo.summary() + "'" + ","
186 + QString::number(m_todo.priority() ) + "," 186 + QString::number(m_todo.priority() ) + ","
187 + "'" + QString::number(year) + "-" 187 + "'" + QString::number(year) + "-"
188 + QString::number(month) 188 + QString::number(month)
189 + "-" + QString::number( day ) + "'" + "," 189 + "-" + QString::number( day ) + "'" + ","
190 + QString::number( m_todo.progress() ) + "," 190 + QString::number( m_todo.progress() ) + ","
191 + QString::number( m_todo.state().state() ) + "," 191 + QString::number( m_todo.state().state() ) + ","
192 + "'" + recMap[ ORecur::RType ] + "'" + "," 192 + "'" + recMap[ ORecur::RType ] + "'" + ","
193 + "'" + recMap[ ORecur::RWeekdays ] + "'" + "," 193 + "'" + recMap[ ORecur::RWeekdays ] + "'" + ","
194 + "'" + recMap[ ORecur::RPosition ] + "'" + "," 194 + "'" + recMap[ ORecur::RPosition ] + "'" + ","
195 + "'" + recMap[ ORecur::RFreq ] + "'" + "," 195 + "'" + recMap[ ORecur::RFreq ] + "'" + ","
196 + "'" + recMap[ ORecur::RHasEndDate ] + "'" + "," 196 + "'" + recMap[ ORecur::RHasEndDate ] + "'" + ","
197 + "'" + recMap[ ORecur::EndDate ] + "'" + "," 197 + "'" + recMap[ ORecur::EndDate ] + "'" + ","
198 + "'" + recMap[ ORecur::Created ] + "'" + "," 198 + "'" + recMap[ ORecur::Created ] + "'" + ","
199 + "'" + recMap[ ORecur::Exceptions ] + "'" + ","; 199 + "'" + recMap[ ORecur::Exceptions ] + "'" + ",";
200 200
201 if ( m_todo.hasNotifiers() ) { 201 if ( m_todo.hasNotifiers() ) {
202 OPimNotifyManager manager = m_todo.notifiers(); 202 OPimNotifyManager manager = m_todo.notifiers();
203 qu += "'" + manager.remindersToString() + "'" + "," 203 qu += "'" + manager.remindersToString() + "'" + ","
204 + "'" + manager.alarmsToString() + "'" + ","; 204 + "'" + manager.alarmsToString() + "'" + ",";
205 } 205 }
206 else{ 206 else{
207 qu += QString( "''" ) + "," 207 qu += QString( "''" ) + ","
208 + "''" + ","; 208 + "''" + ",";
209 } 209 }
210 210
211 qu += QString( "''" ) + QString( "," ) // Maintainers (cur. not supported !) 211 qu += QString( "''" ) + QString( "," ) // Maintainers (cur. not supported !)
212 + "'" + QString::number(sYear) + "-" 212 + "'" + QString::number(sYear) + "-"
213 + QString::number(sMonth) 213 + QString::number(sMonth)
214 + "-" + QString::number(sDay) + "'" + "," 214 + "-" + QString::number(sDay) + "'" + ","
215 + "'" + QString::number(eYear) + "-" 215 + "'" + QString::number(eYear) + "-"
216 + QString::number(eMonth) 216 + QString::number(eMonth)
217 + "-"+QString::number(eDay) + "'" 217 + "-"+QString::number(eDay) + "'"
218 + ")"; 218 + ")";
219 219
220 qWarning("add %s", qu.latin1() ); 220 qWarning("add %s", qu.latin1() );
221 return qu; 221 return qu;
222 } 222 }
223 223
224 RemoveQuery::RemoveQuery(int uid ) 224 RemoveQuery::RemoveQuery(int uid )
225 : OSQLQuery(), m_uid( uid ) {} 225 : OSQLQuery(), m_uid( uid ) {}
226 RemoveQuery::~RemoveQuery() {} 226 RemoveQuery::~RemoveQuery() {}
227 QString RemoveQuery::query()const { 227 QString RemoveQuery::query()const {
228 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid); 228 QString qu = "DELETE from todolist where uid = " + QString::number(m_uid);
229 return qu; 229 return qu;
230 } 230 }
231 231
232 232
233 ClearQuery::ClearQuery() 233 ClearQuery::ClearQuery()
234 : OSQLQuery() {} 234 : OSQLQuery() {}
235 ClearQuery::~ClearQuery() {} 235 ClearQuery::~ClearQuery() {}
236 QString ClearQuery::query()const { 236 QString ClearQuery::query()const {
237 QString qu = "drop table todolist"; 237 QString qu = "drop table todolist";
238 return qu; 238 return qu;
239 } 239 }
240 FindQuery::FindQuery(int uid) 240 FindQuery::FindQuery(int uid)
241 : OSQLQuery(), m_uid(uid ) { 241 : OSQLQuery(), m_uid(uid ) {
242 } 242 }
243 FindQuery::FindQuery(const QArray<int>& ints) 243 FindQuery::FindQuery(const QArray<int>& ints)
244 : OSQLQuery(), m_uids(ints){ 244 : OSQLQuery(), m_uids(ints){
245 } 245 }
246 FindQuery::~FindQuery() { 246 FindQuery::~FindQuery() {
247 } 247 }
248 QString FindQuery::query()const{ 248 QString FindQuery::query()const{
249 if (m_uids.count() == 0 ) 249 if (m_uids.count() == 0 )
250 return single(); 250 return single();
251 else 251 else
252 return multi(); 252 return multi();
253 } 253 }
254 QString FindQuery::single()const{ 254 QString FindQuery::single()const{
255 QString qu = "select * from todolist where uid = " + QString::number(m_uid); 255 QString qu = "select * from todolist where uid = " + QString::number(m_uid);
256 return qu; 256 return qu;
257 } 257 }
258 QString FindQuery::multi()const { 258 QString FindQuery::multi()const {
259 QString qu = "select * from todolist where "; 259 QString qu = "select * from todolist where ";
260 for (uint i = 0; i < m_uids.count(); i++ ) { 260 for (uint i = 0; i < m_uids.count(); i++ ) {
261 qu += " UID = " + QString::number( m_uids[i] ) + " OR"; 261 qu += " UID = " + QString::number( m_uids[i] ) + " OR";
262 } 262 }
263 qu.remove( qu.length()-2, 2 ); 263 qu.remove( qu.length()-2, 2 );
264 return qu; 264 return qu;
265 } 265 }
266 266
267 OverDueQuery::OverDueQuery(): OSQLQuery() {} 267 OverDueQuery::OverDueQuery(): OSQLQuery() {}
268 OverDueQuery::~OverDueQuery() {} 268 OverDueQuery::~OverDueQuery() {}
269 QString OverDueQuery::query()const { 269 QString OverDueQuery::query()const {
270 QDate date = QDate::currentDate(); 270 QDate date = QDate::currentDate();
271 QString str; 271 QString str;
272 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() ); 272 str = QString("select uid from todolist where DueDate ='%1-%2-%3'").arg(date.year() ).arg(date.month() ).arg(date.day() );
273 273
274 return str; 274 return str;
275 } 275 }
276 276
277 277
278 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc ) 278 EffQuery::EffQuery( const QDate& start, const QDate& end, bool inc )
279 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {} 279 : OSQLQuery(), m_start( start ), m_end( end ),m_inc(inc) {}
280 EffQuery::~EffQuery() {} 280 EffQuery::~EffQuery() {}
281 QString EffQuery::query()const { 281 QString EffQuery::query()const {
282 return m_inc ? with() : out(); 282 return m_inc ? with() : out();
283 } 283 }
284 QString EffQuery::with()const { 284 QString EffQuery::with()const {
285 QString str; 285 QString str;
286 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ") 286 str = QString("select uid from todolist where ( DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6' ) OR DueDate = '0-0-0' ")
287 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() ) 287 .arg( m_start.year() ).arg( m_start.month() ).arg( m_start.day() )
288 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() ); 288 .arg( m_end .year() ).arg( m_end .month() ).arg( m_end .day() );
289 return str; 289 return str;
290 } 290 }
291 QString EffQuery::out()const { 291 QString EffQuery::out()const {
292 QString str; 292 QString str;
293 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'") 293 str = QString("select uid from todolist where DueDate >= '%1-%2-%3' AND DueDate <= '%4-%5-%6'")
294 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() ) 294 .arg(m_start.year() ).arg(m_start.month() ).arg( m_start.day() )
295 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() ); 295 .arg(m_end. year() ).arg(m_end. month() ).arg(m_end.day() );
296 296
297 return str; 297 return str;
298 } 298 }
299}; 299};
300 300
301OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file ) 301OTodoAccessBackendSQL::OTodoAccessBackendSQL( const QString& file )
302 : OTodoAccessBackend(), m_dict(15), m_dirty(true) 302 : OTodoAccessBackend(), m_dict(15), m_driver(NULL), m_dirty(true)
303{ 303{
304 QString fi = file; 304 QString fi = file;
305 if ( fi.isEmpty() ) 305 if ( fi.isEmpty() )
306 fi = Global::applicationFileName( "todolist", "todolist.db" ); 306 fi = Global::applicationFileName( "todolist", "todolist.db" );
307 OSQLManager man; 307 OSQLManager man;
308 m_driver = man.standard(); 308 m_driver = man.standard();
309 m_driver->setUrl(fi); 309 m_driver->setUrl(fi);
310 // fillDict(); 310 // fillDict();
311} 311}
312 312
313OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){ 313OTodoAccessBackendSQL::~OTodoAccessBackendSQL(){
314 if( m_driver )
315 delete m_driver;
314} 316}
317
315bool OTodoAccessBackendSQL::load(){ 318bool OTodoAccessBackendSQL::load(){
316 if (!m_driver->open() ) 319 if (!m_driver->open() )
317 return false; 320 return false;
318 321
319 CreateQuery creat; 322 CreateQuery creat;
320 OSQLResult res = m_driver->query(&creat ); 323 OSQLResult res = m_driver->query(&creat );
321 324
322 m_dirty = true; 325 m_dirty = true;
323 return true; 326 return true;
324} 327}
325bool OTodoAccessBackendSQL::reload(){ 328bool OTodoAccessBackendSQL::reload(){
326 return load(); 329 return load();
327} 330}
328 331
329bool OTodoAccessBackendSQL::save(){ 332bool OTodoAccessBackendSQL::save(){
330 return m_driver->close(); 333 return m_driver->close();
331} 334}
332QArray<int> OTodoAccessBackendSQL::allRecords()const { 335QArray<int> OTodoAccessBackendSQL::allRecords()const {
333 if (m_dirty ) 336 if (m_dirty )
334 update(); 337 update();
335 338
336 return m_uids; 339 return m_uids;
337} 340}
338QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){ 341QArray<int> OTodoAccessBackendSQL::queryByExample( const OTodo& , int, const QDateTime& ){
339 QArray<int> ints(0); 342 QArray<int> ints(0);
340 return ints; 343 return ints;
341} 344}
342OTodo OTodoAccessBackendSQL::find(int uid ) const{ 345OTodo OTodoAccessBackendSQL::find(int uid ) const{
343 FindQuery query( uid ); 346 FindQuery query( uid );
344 return todo( m_driver->query(&query) ); 347 return todo( m_driver->query(&query) );
345 348
346} 349}
347OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints, 350OTodo OTodoAccessBackendSQL::find( int uid, const QArray<int>& ints,
348 uint cur, Frontend::CacheDirection dir ) const{ 351 uint cur, Frontend::CacheDirection dir ) const{
349 uint CACHE = readAhead(); 352 uint CACHE = readAhead();
350 qWarning("searching for %d", uid ); 353 qWarning("searching for %d", uid );
351 QArray<int> search( CACHE ); 354 QArray<int> search( CACHE );
352 uint size =0; 355 uint size =0;
353 OTodo to; 356 OTodo to;
354 357
355 // we try to cache CACHE items 358 // we try to cache CACHE items
356 switch( dir ) { 359 switch( dir ) {
357 /* forward */ 360 /* forward */
358 case 0: // FIXME: Not a good style to use magic numbers here (eilers) 361 case 0: // FIXME: Not a good style to use magic numbers here (eilers)
359 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) { 362 for (uint i = cur; i < ints.count() && size < CACHE; i++ ) {
360 qWarning("size %d %d", size, ints[i] ); 363 qWarning("size %d %d", size, ints[i] );
361 search[size] = ints[i]; 364 search[size] = ints[i];
362 size++; 365 size++;
363 } 366 }
364 break; 367 break;
365 /* reverse */ 368 /* reverse */
366 case 1: // FIXME: Not a good style to use magic numbers here (eilers) 369 case 1: // FIXME: Not a good style to use magic numbers here (eilers)
367 for (uint i = cur; i != 0 && size < CACHE; i-- ) { 370 for (uint i = cur; i != 0 && size < CACHE; i-- ) {
368 search[size] = ints[i]; 371 search[size] = ints[i];
369 size++; 372 size++;
370 } 373 }
371 break; 374 break;
372 } 375 }
373 search.resize( size ); 376 search.resize( size );
374 FindQuery query( search ); 377 FindQuery query( search );
375 OSQLResult res = m_driver->query( &query ); 378 OSQLResult res = m_driver->query( &query );
376 if ( res.state() != OSQLResult::Success ) 379 if ( res.state() != OSQLResult::Success )
377 return to; 380 return to;
378 381
379 return todo( res ); 382 return todo( res );
380} 383}
381void OTodoAccessBackendSQL::clear() { 384void OTodoAccessBackendSQL::clear() {
382 ClearQuery cle; 385 ClearQuery cle;
383 OSQLResult res = m_driver->query( &cle ); 386 OSQLResult res = m_driver->query( &cle );
384 CreateQuery qu; 387 CreateQuery qu;
385 res = m_driver->query(&qu); 388 res = m_driver->query(&qu);
386} 389}
387bool OTodoAccessBackendSQL::add( const OTodo& t) { 390bool OTodoAccessBackendSQL::add( const OTodo& t) {
388 InsertQuery ins( t ); 391 InsertQuery ins( t );
389 OSQLResult res = m_driver->query( &ins ); 392 OSQLResult res = m_driver->query( &ins );
390 393
391 if ( res.state() == OSQLResult::Failure ) 394 if ( res.state() == OSQLResult::Failure )
392 return false; 395 return false;
393 int c = m_uids.count(); 396 int c = m_uids.count();
394 m_uids.resize( c+1 ); 397 m_uids.resize( c+1 );
395 m_uids[c] = t.uid(); 398 m_uids[c] = t.uid();
396 399
397 return true; 400 return true;
398} 401}
399bool OTodoAccessBackendSQL::remove( int uid ) { 402bool OTodoAccessBackendSQL::remove( int uid ) {
400 RemoveQuery rem( uid ); 403 RemoveQuery rem( uid );
401 OSQLResult res = m_driver->query(&rem ); 404 OSQLResult res = m_driver->query(&rem );
402 405
403 if ( res.state() == OSQLResult::Failure ) 406 if ( res.state() == OSQLResult::Failure )
404 return false; 407 return false;
405 408
406 m_dirty = true; 409 m_dirty = true;
407 return true; 410 return true;
408} 411}
409/* 412/*
410 * FIXME better set query 413 * FIXME better set query
411 * but we need the cache for that 414 * but we need the cache for that
412 * now we remove 415 * now we remove
413 */ 416 */
414bool OTodoAccessBackendSQL::replace( const OTodo& t) { 417bool OTodoAccessBackendSQL::replace( const OTodo& t) {
415 remove( t.uid() ); 418 remove( t.uid() );
416 bool b= add(t); 419 bool b= add(t);
417 m_dirty = false; // we changed some stuff but the UID stayed the same 420 m_dirty = false; // we changed some stuff but the UID stayed the same
418 return b; 421 return b;
419} 422}
420QArray<int> OTodoAccessBackendSQL::overDue() { 423QArray<int> OTodoAccessBackendSQL::overDue() {
421 OverDueQuery qu; 424 OverDueQuery qu;
422 return uids( m_driver->query(&qu ) ); 425 return uids( m_driver->query(&qu ) );
423} 426}
424QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s, 427QArray<int> OTodoAccessBackendSQL::effectiveToDos( const QDate& s,
425 const QDate& t, 428 const QDate& t,
426 bool u) { 429 bool u) {
427 EffQuery ef(s, t, u ); 430 EffQuery ef(s, t, u );
428 return uids (m_driver->query(&ef) ); 431 return uids (m_driver->query(&ef) );
429} 432}
430/* 433/*
431 * 434 *
432 */ 435 */
433QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder, 436QArray<int> OTodoAccessBackendSQL::sorted( bool asc, int sortOrder,
434 int sortFilter, int cat ) { 437 int sortFilter, int cat ) {
435 qWarning("sorted %d, %d", asc, sortOrder ); 438 qWarning("sorted %d, %d", asc, sortOrder );
436 QString query; 439 QString query;
437 query = "select uid from todolist WHERE "; 440 query = "select uid from todolist WHERE ";
438 441
439 /* 442 /*
440 * Sort Filter stuff 443 * Sort Filter stuff
441 * not that straight forward 444 * not that straight forward
442 * FIXME: Replace magic numbers 445 * FIXME: Replace magic numbers
443 * 446 *
444 */ 447 */
445 /* Category */ 448 /* Category */
446 if ( sortFilter & 1 ) { 449 if ( sortFilter & 1 ) {
447 QString str; 450 QString str;
448 if (cat != 0 ) str = QString::number( cat ); 451 if (cat != 0 ) str = QString::number( cat );
449 query += " categories like '%" +str+"%' AND"; 452 query += " categories like '%" +str+"%' AND";
450 } 453 }
451 /* Show only overdue */ 454 /* Show only overdue */
452 if ( sortFilter & 2 ) { 455 if ( sortFilter & 2 ) {
453 QDate date = QDate::currentDate(); 456 QDate date = QDate::currentDate();
454 QString due; 457 QString due;
455 QString base; 458 QString base;
456 base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() ); 459 base = QString("DueDate <= '%1-%2-%3' AND completed = 0").arg( date.year() ).arg( date.month() ).arg( date.day() );
457 query += " " + base + " AND"; 460 query += " " + base + " AND";
458 } 461 }
459 /* not show completed */ 462 /* not show completed */
460 if ( sortFilter & 4 ) { 463 if ( sortFilter & 4 ) {
461 query += " completed = 0 AND"; 464 query += " completed = 0 AND";
462 }else{ 465 }else{
463 query += " ( completed = 1 OR completed = 0) AND"; 466 query += " ( completed = 1 OR completed = 0) AND";
464 } 467 }
465 /* srtip the end */ 468 /* srtip the end */
466 query = query.remove( query.length()-3, 3 ); 469 query = query.remove( query.length()-3, 3 );
467 470
468 471
469 /* 472 /*
470 * sort order stuff 473 * sort order stuff
471 * quite straight forward 474 * quite straight forward
472 */ 475 */
473 query += "ORDER BY "; 476 query += "ORDER BY ";
474 switch( sortOrder ) { 477 switch( sortOrder ) {
475 /* completed */ 478 /* completed */
476 case 0: 479 case 0:
477 query += "completed"; 480 query += "completed";
478 break; 481 break;
479 case 1: 482 case 1:
480 query += "priority"; 483 query += "priority";
481 break; 484 break;
482 case 2: 485 case 2:
483 query += "summary"; 486 query += "summary";
484 break; 487 break;
485 case 3: 488 case 3:
486 query += "DueDate"; 489 query += "DueDate";
487 break; 490 break;
488 } 491 }
489 492
490 if ( !asc ) { 493 if ( !asc ) {
491 qWarning("not ascending!"); 494 qWarning("not ascending!");
492 query += " DESC"; 495 query += " DESC";
493 } 496 }
494 497
495 qWarning( query ); 498 qWarning( query );
496 OSQLRawQuery raw(query ); 499 OSQLRawQuery raw(query );
497 return uids( m_driver->query(&raw) ); 500 return uids( m_driver->query(&raw) );
498} 501}
499bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{ 502bool OTodoAccessBackendSQL::date( QDate& da, const QString& str ) const{
500 if ( str == "0-0-0" ) 503 if ( str == "0-0-0" )
501 return false; 504 return false;
502 else{ 505 else{
503 int day, year, month; 506 int day, year, month;
504 QStringList list = QStringList::split("-", str ); 507 QStringList list = QStringList::split("-", str );
505 year = list[0].toInt(); 508 year = list[0].toInt();
506 month = list[1].toInt(); 509 month = list[1].toInt();
507 day = list[2].toInt(); 510 day = list[2].toInt();
508 da.setYMD( year, month, day ); 511 da.setYMD( year, month, day );
509 return true; 512 return true;
510 } 513 }
511} 514}
512OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{ 515OTodo OTodoAccessBackendSQL::todo( const OSQLResult& res) const{
513 if ( res.state() == OSQLResult::Failure ) { 516 if ( res.state() == OSQLResult::Failure ) {
514 OTodo to; 517 OTodo to;
515 return to; 518 return to;
516 } 519 }
517 520
518 OSQLResultItem::ValueList list = res.results(); 521 OSQLResultItem::ValueList list = res.results();
519 OSQLResultItem::ValueList::Iterator it = list.begin(); 522 OSQLResultItem::ValueList::Iterator it = list.begin();
520 qWarning("todo1"); 523 qWarning("todo1");
521 OTodo to = todo( (*it) ); 524 OTodo to = todo( (*it) );
522 cache( to ); 525 cache( to );
523 ++it; 526 ++it;
524 527
525 for ( ; it != list.end(); ++it ) { 528 for ( ; it != list.end(); ++it ) {
526 qWarning("caching"); 529 qWarning("caching");
527 cache( todo( (*it) ) ); 530 cache( todo( (*it) ) );
528 } 531 }
529 return to; 532 return to;
530} 533}
531OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const { 534OTodo OTodoAccessBackendSQL::todo( OSQLResultItem& item )const {
532 qWarning("todo"); 535 qWarning("todo");
533 bool hasDueDate = false; QDate dueDate = QDate::currentDate(); 536 bool hasDueDate = false; QDate dueDate = QDate::currentDate();
534 hasDueDate = date( dueDate, item.data("DueDate") ); 537 hasDueDate = date( dueDate, item.data("DueDate") );
535 QStringList cats = QStringList::split(";", item.data("categories") ); 538 QStringList cats = QStringList::split(";", item.data("categories") );
536 539
537 qWarning("Item is completed: %d", item.data("completed").toInt() ); 540 qWarning("Item is completed: %d", item.data("completed").toInt() );
538 541
539 OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(), 542 OTodo to( (bool)item.data("completed").toInt(), item.data("priority").toInt(),
540 cats, item.data("summary"), item.data("description"), 543 cats, item.data("summary"), item.data("description"),
541 item.data("progress").toUShort(), hasDueDate, dueDate, 544 item.data("progress").toUShort(), hasDueDate, dueDate,
542 item.data("uid").toInt() ); 545 item.data("uid").toInt() );
543 546
544 bool isOk; 547 bool isOk;
545 int prioInt = QString( item.data("priority") ).toInt( &isOk ); 548 int prioInt = QString( item.data("priority") ).toInt( &isOk );
546 if ( isOk ) 549 if ( isOk )
547 to.setPriority( prioInt ); 550 to.setPriority( prioInt );
548 551
549 bool hasStartDate = false; QDate startDate = QDate::currentDate(); 552 bool hasStartDate = false; QDate startDate = QDate::currentDate();
550 hasStartDate = date( startDate, item.data("startdate") ); 553 hasStartDate = date( startDate, item.data("startdate") );
551 bool hasCompletedDate = false; QDate completedDate = QDate::currentDate(); 554 bool hasCompletedDate = false; QDate completedDate = QDate::currentDate();
552 hasCompletedDate = date( completedDate, item.data("completeddate") ); 555 hasCompletedDate = date( completedDate, item.data("completeddate") );
553 556
554 if ( hasStartDate ) 557 if ( hasStartDate )
555 to.setStartDate( startDate ); 558 to.setStartDate( startDate );
556 if ( hasCompletedDate ) 559 if ( hasCompletedDate )
557 to.setCompletedDate( completedDate ); 560 to.setCompletedDate( completedDate );
558 561
559 OPimNotifyManager& manager = to.notifiers(); 562 OPimNotifyManager& manager = to.notifiers();
560 manager.alarmsFromString( item.data("alarms") ); 563 manager.alarmsFromString( item.data("alarms") );
561 manager.remindersFromString( item.data("reminders") ); 564 manager.remindersFromString( item.data("reminders") );
562 565
563 OPimState pimState; 566 OPimState pimState;
564 pimState.setState( QString( item.data("state") ).toInt() ); 567 pimState.setState( QString( item.data("state") ).toInt() );
565 to.setState( pimState ); 568 to.setState( pimState );
566 569
567 QMap<int, QString> recMap; 570 QMap<int, QString> recMap;
568 recMap.insert( ORecur::RType , item.data("RType") ); 571 recMap.insert( ORecur::RType , item.data("RType") );
569 recMap.insert( ORecur::RWeekdays , item.data("RWeekdays") ); 572 recMap.insert( ORecur::RWeekdays , item.data("RWeekdays") );
570 recMap.insert( ORecur::RPosition , item.data("RPosition") ); 573 recMap.insert( ORecur::RPosition , item.data("RPosition") );
diff --git a/libopie2/opiepim/core/orecur.cpp b/libopie2/opiepim/core/orecur.cpp
index 8c9ad46..f46f22e 100644
--- a/libopie2/opiepim/core/orecur.cpp
+++ b/libopie2/opiepim/core/orecur.cpp
@@ -1,292 +1,300 @@
1#include <time.h> 1#include <time.h>
2 2
3#include <qshared.h> 3#include <qshared.h>
4 4
5#include <qtopia/timeconversion.h> 5#include <qtopia/timeconversion.h>
6 6
7#include "otimezone.h" 7#include "otimezone.h"
8#include "orecur.h" 8#include "orecur.h"
9 9
10struct ORecur::Data : public QShared { 10struct ORecur::Data : public QShared {
11 Data() : QShared() { 11 Data() : QShared() {
12 type = ORecur::NoRepeat; 12 type = ORecur::NoRepeat;
13 freq = -1; 13 freq = -1;
14 days = 0; 14 days = 0;
15 pos = 0; 15 pos = 0;
16 create = QDateTime::currentDateTime(); 16 create = QDateTime::currentDateTime();
17 hasEnd = FALSE; 17 hasEnd = FALSE;
18 end = QDate::currentDate(); 18 end = QDate::currentDate();
19 } 19 }
20 char days; // Q_UINT8 for 8 seven days;) 20 char days; // Q_UINT8 for 8 seven days;)
21 ORecur::RepeatType type; 21 ORecur::RepeatType type;
22 int freq; 22 int freq;
23 int pos; 23 int pos;
24 bool hasEnd : 1; 24 bool hasEnd : 1;
25 QDate end; 25 QDate end;
26 QDateTime create; 26 QDateTime create;
27 int rep; 27 int rep;
28 QString app; 28 QString app;
29 ExceptionList list; 29 ExceptionList list;
30 QDate start; 30 QDate start;
31}; 31};
32 32
33 33
34ORecur::ORecur() { 34ORecur::ORecur() {
35 data = new Data; 35 data = new Data;
36} 36}
37
38ORecur::ORecur( const QMap<int, QString>& map )
39{
40 ORecur();
41 fromMap( map );
42}
43
44
37ORecur::ORecur( const ORecur& rec) 45ORecur::ORecur( const ORecur& rec)
38 : data( rec.data ) 46 : data( rec.data )
39{ 47{
40 data->ref(); 48 data->ref();
41} 49}
42ORecur::~ORecur() { 50ORecur::~ORecur() {
43 if ( data->deref() ) { 51 if ( data->deref() ) {
44 delete data; 52 delete data;
45 data = 0l; 53 data = 0l;
46 } 54 }
47} 55}
48void ORecur::deref() { 56void ORecur::deref() {
49 if ( data->deref() ) { 57 if ( data->deref() ) {
50 delete data; 58 delete data;
51 data = 0l; 59 data = 0l;
52 } 60 }
53} 61}
54bool ORecur::operator==( const ORecur& )const { 62bool ORecur::operator==( const ORecur& )const {
55 return false; 63 return false;
56} 64}
57ORecur &ORecur::operator=( const ORecur& re) { 65ORecur &ORecur::operator=( const ORecur& re) {
58 if ( *this == re ) return *this; 66 if ( *this == re ) return *this;
59 67
60 re.data->ref(); 68 re.data->ref();
61 deref(); 69 deref();
62 data = re.data; 70 data = re.data;
63 71
64 return *this; 72 return *this;
65} 73}
66bool ORecur::doesRecur()const { 74bool ORecur::doesRecur()const {
67 return !( type() == NoRepeat ); 75 return !( type() == NoRepeat );
68} 76}
69/* 77/*
70 * we try to be smart here 78 * we try to be smart here
71 * 79 *
72 */ 80 */
73bool ORecur::doesRecur( const QDate& date ) { 81bool ORecur::doesRecur( const QDate& date ) {
74 /* the day before the recurrance */ 82 /* the day before the recurrance */
75 QDate da = date.addDays(-1); 83 QDate da = date.addDays(-1);
76 84
77 QDate recur; 85 QDate recur;
78 if (!nextOcurrence( da, recur ) ) 86 if (!nextOcurrence( da, recur ) )
79 return false; 87 return false;
80 88
81 return (recur == date); 89 return (recur == date);
82} 90}
83// FIXME unuglify! 91// FIXME unuglify!
84// GPL from Datebookdb.cpp 92// GPL from Datebookdb.cpp
85// FIXME exception list! 93// FIXME exception list!
86bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { 94bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
87 bool stillLooking; 95 bool stillLooking;
88 stillLooking = p_nextOccurrence( from, next ); 96 stillLooking = p_nextOccurrence( from, next );
89 while ( stillLooking && data->list.contains(next) ) 97 while ( stillLooking && data->list.contains(next) )
90 stillLooking = p_nextOccurrence( next.addDays(1), next ); 98 stillLooking = p_nextOccurrence( next.addDays(1), next );
91 99
92 return stillLooking; 100 return stillLooking;
93} 101}
94bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) { 102bool ORecur::p_nextOccurrence( const QDate& from, QDate& next ) {
95 103
96 // easy checks, first are we too far in the future or too far in the past? 104 // easy checks, first are we too far in the future or too far in the past?
97 QDate tmpDate; 105 QDate tmpDate;
98 int freq = frequency(); 106 int freq = frequency();
99 int diff, diff2, a; 107 int diff, diff2, a;
100 int iday, imonth, iyear; 108 int iday, imonth, iyear;
101 int dayOfWeek = 0; 109 int dayOfWeek = 0;
102 int firstOfWeek = 0; 110 int firstOfWeek = 0;
103 int weekOfMonth; 111 int weekOfMonth;
104 112
105 113
106 if (hasEndDate() && endDate() < from) 114 if (hasEndDate() && endDate() < from)
107 return FALSE; 115 return FALSE;
108 116
109 if (start() >= from ) { 117 if (start() >= from ) {
110 next = start(); 118 next = start();
111 return TRUE; 119 return TRUE;
112 } 120 }
113 121
114 switch ( type() ) { 122 switch ( type() ) {
115 case Weekly: 123 case Weekly:
116 /* weekly is just daily by 7 */ 124 /* weekly is just daily by 7 */
117 /* first convert the repeatPattern.Days() mask to the next 125 /* first convert the repeatPattern.Days() mask to the next
118 day of week valid after from */ 126 day of week valid after from */
119 dayOfWeek = from.dayOfWeek(); 127 dayOfWeek = from.dayOfWeek();
120 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */ 128 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */
121 129
122 /* this is done in case freq > 1 and from in week not 130 /* this is done in case freq > 1 and from in week not
123 for this round */ 131 for this round */
124 // firstOfWeek = 0; this is already done at decl. 132 // firstOfWeek = 0; this is already done at decl.
125 while(!((1 << firstOfWeek) & days() )) 133 while(!((1 << firstOfWeek) & days() ))
126 firstOfWeek++; 134 firstOfWeek++;
127 135
128 /* there is at least one 'day', or there would be no event */ 136 /* there is at least one 'day', or there would be no event */
129 while(!((1 << (dayOfWeek % 7)) & days() )) 137 while(!((1 << (dayOfWeek % 7)) & days() ))
130 dayOfWeek++; 138 dayOfWeek++;
131 139
132 dayOfWeek = dayOfWeek % 7; /* the actual day of week */ 140 dayOfWeek = dayOfWeek % 7; /* the actual day of week */
133 dayOfWeek -= start().dayOfWeek() -1; 141 dayOfWeek -= start().dayOfWeek() -1;
134 142
135 firstOfWeek = firstOfWeek % 7; /* the actual first of week */ 143 firstOfWeek = firstOfWeek % 7; /* the actual first of week */
136 firstOfWeek -= start().dayOfWeek() -1; 144 firstOfWeek -= start().dayOfWeek() -1;
137 145
138 // dayOfWeek may be negitive now 146 // dayOfWeek may be negitive now
139 // day of week is number of days to add to start day 147 // day of week is number of days to add to start day
140 148
141 freq *= 7; 149 freq *= 7;
142 // FALL-THROUGH !!!!! 150 // FALL-THROUGH !!!!!
143 case Daily: 151 case Daily:
144 // the add is for the possible fall through from weekly */ 152 // the add is for the possible fall through from weekly */
145 if(start().addDays(dayOfWeek) > from) { 153 if(start().addDays(dayOfWeek) > from) {
146 /* first week exception */ 154 /* first week exception */
147 next = QDate(start().addDays(dayOfWeek) ); 155 next = QDate(start().addDays(dayOfWeek) );
148 if ((next > endDate()) 156 if ((next > endDate())
149 && hasEndDate() ) 157 && hasEndDate() )
150 return FALSE; 158 return FALSE;
151 return TRUE; 159 return TRUE;
152 } 160 }
153 /* if from is middle of a non-week */ 161 /* if from is middle of a non-week */
154 162
155 diff = start().addDays(dayOfWeek).daysTo(from) % freq; 163 diff = start().addDays(dayOfWeek).daysTo(from) % freq;
156 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq; 164 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
157 165
158 if(diff != 0) 166 if(diff != 0)
159 diff = freq - diff; 167 diff = freq - diff;
160 if(diff2 != 0) 168 if(diff2 != 0)
161 diff2 = freq - diff2; 169 diff2 = freq - diff2;
162 diff = QMIN(diff, diff2); 170 diff = QMIN(diff, diff2);
163 171
164 next = QDate(from.addDays(diff)); 172 next = QDate(from.addDays(diff));
165 if ( (next > endDate()) 173 if ( (next > endDate())
166 && hasEndDate() ) 174 && hasEndDate() )
167 return FALSE; 175 return FALSE;
168 return TRUE; 176 return TRUE;
169 case MonthlyDay: 177 case MonthlyDay:
170 iday = from.day(); 178 iday = from.day();
171 iyear = from.year(); 179 iyear = from.year();
172 imonth = from.month(); 180 imonth = from.month();
173 /* find equivelent day of month for this month */ 181 /* find equivelent day of month for this month */
174 dayOfWeek = start().dayOfWeek(); 182 dayOfWeek = start().dayOfWeek();
175 weekOfMonth = (start().day() - 1) / 7; 183 weekOfMonth = (start().day() - 1) / 7;
176 184
177 /* work out when the next valid month is */ 185 /* work out when the next valid month is */
178 a = from.year() - start().year(); 186 a = from.year() - start().year();
179 a *= 12; 187 a *= 12;
180 a = a + (imonth - start().month()); 188 a = a + (imonth - start().month());
181 /* a is e.start()monthsFrom(from); */ 189 /* a is e.start()monthsFrom(from); */
182 if(a % freq) { 190 if(a % freq) {
183 a = freq - (a % freq); 191 a = freq - (a % freq);
184 imonth = from.month() + a; 192 imonth = from.month() + a;
185 if (imonth > 12) { 193 if (imonth > 12) {
186 imonth--; 194 imonth--;
187 iyear += imonth / 12; 195 iyear += imonth / 12;
188 imonth = imonth % 12; 196 imonth = imonth % 12;
189 imonth++; 197 imonth++;
190 } 198 }
191 } 199 }
192 /* imonth is now the first month after or on 200 /* imonth is now the first month after or on
193 from that matches the frequency given */ 201 from that matches the frequency given */
194 202
195 /* find for this month */ 203 /* find for this month */
196 tmpDate = QDate( iyear, imonth, 1 ); 204 tmpDate = QDate( iyear, imonth, 1 );
197 205
198 iday = 1; 206 iday = 1;
199 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 207 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
200 iday += 7 * weekOfMonth; 208 iday += 7 * weekOfMonth;
201 while (iday > tmpDate.daysInMonth()) { 209 while (iday > tmpDate.daysInMonth()) {
202 imonth += freq; 210 imonth += freq;
203 if (imonth > 12) { 211 if (imonth > 12) {
204 imonth--; 212 imonth--;
205 iyear += imonth / 12; 213 iyear += imonth / 12;
206 imonth = imonth % 12; 214 imonth = imonth % 12;
207 imonth++; 215 imonth++;
208 } 216 }
209 tmpDate = QDate( iyear, imonth, 1 ); 217 tmpDate = QDate( iyear, imonth, 1 );
210 /* these loops could go for a while, check end case now */ 218 /* these loops could go for a while, check end case now */
211 if ((tmpDate > endDate()) && hasEndDate() ) 219 if ((tmpDate > endDate()) && hasEndDate() )
212 return FALSE; 220 return FALSE;
213 iday = 1; 221 iday = 1;
214 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 222 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
215 iday += 7 * weekOfMonth; 223 iday += 7 * weekOfMonth;
216 } 224 }
217 tmpDate = QDate(iyear, imonth, iday); 225 tmpDate = QDate(iyear, imonth, iday);
218 226
219 if (tmpDate >= from) { 227 if (tmpDate >= from) {
220 next = tmpDate; 228 next = tmpDate;
221 if ((next > endDate() ) && hasEndDate() ) 229 if ((next > endDate() ) && hasEndDate() )
222 return FALSE; 230 return FALSE;
223 return TRUE; 231 return TRUE;
224 } 232 }
225 233
226 /* need to find the next iteration */ 234 /* need to find the next iteration */
227 do { 235 do {
228 imonth += freq; 236 imonth += freq;
229 if (imonth > 12) { 237 if (imonth > 12) {
230 imonth--; 238 imonth--;
231 iyear += imonth / 12; 239 iyear += imonth / 12;
232 imonth = imonth % 12; 240 imonth = imonth % 12;
233 imonth++; 241 imonth++;
234 } 242 }
235 tmpDate = QDate( iyear, imonth, 1 ); 243 tmpDate = QDate( iyear, imonth, 1 );
236 /* these loops could go for a while, check end case now */ 244 /* these loops could go for a while, check end case now */
237 if ((tmpDate > endDate()) && hasEndDate() ) 245 if ((tmpDate > endDate()) && hasEndDate() )
238 return FALSE; 246 return FALSE;
239 iday = 1; 247 iday = 1;
240 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7; 248 iday += (7 + dayOfWeek - tmpDate.dayOfWeek()) % 7;
241 iday += 7 * weekOfMonth; 249 iday += 7 * weekOfMonth;
242 } while (iday > tmpDate.daysInMonth()); 250 } while (iday > tmpDate.daysInMonth());
243 tmpDate = QDate(iyear, imonth, iday); 251 tmpDate = QDate(iyear, imonth, iday);
244 252
245 next = tmpDate; 253 next = tmpDate;
246 if ((next > endDate()) && hasEndDate() ) 254 if ((next > endDate()) && hasEndDate() )
247 return FALSE; 255 return FALSE;
248 return TRUE; 256 return TRUE;
249 case MonthlyDate: 257 case MonthlyDate:
250 iday = start().day(); 258 iday = start().day();
251 iyear = from.year(); 259 iyear = from.year();
252 imonth = from.month(); 260 imonth = from.month();
253 261
254 a = from.year() - start().year(); 262 a = from.year() - start().year();
255 a *= 12; 263 a *= 12;
256 a = a + (imonth - start().month()); 264 a = a + (imonth - start().month());
257 /* a is e.start()monthsFrom(from); */ 265 /* a is e.start()monthsFrom(from); */
258 if(a % freq) { 266 if(a % freq) {
259 a = freq - (a % freq); 267 a = freq - (a % freq);
260 imonth = from.month() + a; 268 imonth = from.month() + a;
261 if (imonth > 12) { 269 if (imonth > 12) {
262 imonth--; 270 imonth--;
263 iyear += imonth / 12; 271 iyear += imonth / 12;
264 imonth = imonth % 12; 272 imonth = imonth % 12;
265 imonth++; 273 imonth++;
266 } 274 }
267 } 275 }
268 /* imonth is now the first month after or on 276 /* imonth is now the first month after or on
269 from that matches the frequencey given */ 277 from that matches the frequencey given */
270 278
271 /* this could go for a while, worse case, 4*12 iterations, probably */ 279 /* this could go for a while, worse case, 4*12 iterations, probably */
272 while(!QDate::isValid(iyear, imonth, iday) ) { 280 while(!QDate::isValid(iyear, imonth, iday) ) {
273 imonth += freq; 281 imonth += freq;
274 if (imonth > 12) { 282 if (imonth > 12) {
275 imonth--; 283 imonth--;
276 iyear += imonth / 12; 284 iyear += imonth / 12;
277 imonth = imonth % 12; 285 imonth = imonth % 12;
278 imonth++; 286 imonth++;
279 } 287 }
280 /* these loops could go for a while, check end case now */ 288 /* these loops could go for a while, check end case now */
281 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 289 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
282 return FALSE; 290 return FALSE;
283 } 291 }
284 292
285 if(QDate(iyear, imonth, iday) >= from) { 293 if(QDate(iyear, imonth, iday) >= from) {
286 /* done */ 294 /* done */
287 next = QDate(iyear, imonth, iday); 295 next = QDate(iyear, imonth, iday);
288 if ((next > endDate()) && hasEndDate() ) 296 if ((next > endDate()) && hasEndDate() )
289 return FALSE; 297 return FALSE;
290 return TRUE; 298 return TRUE;
291 } 299 }
292 300
diff --git a/libopie2/opiepim/core/orecur.h b/libopie2/opiepim/core/orecur.h
index 47901b0..7750c12 100644
--- a/libopie2/opiepim/core/orecur.h
+++ b/libopie2/opiepim/core/orecur.h
@@ -1,101 +1,102 @@
1/* 1/*
2 * GPL from TT 2 * GPL from TT
3 */ 3 */
4 4
5#ifndef OPIE_RECUR_H 5#ifndef OPIE_RECUR_H
6#define OPIE_RECUR_H 6#define OPIE_RECUR_H
7 7
8#include <sys/types.h> 8#include <sys/types.h>
9 9
10#include <qdatetime.h> 10#include <qdatetime.h>
11#include <qvaluelist.h> 11#include <qvaluelist.h>
12#include <qmap.h> 12#include <qmap.h>
13 13
14class ORecur { 14class ORecur {
15public: 15public:
16 typedef QValueList<QDate> ExceptionList; 16 typedef QValueList<QDate> ExceptionList;
17 enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay, 17 enum RepeatType{ NoRepeat = -1, Daily, Weekly, MonthlyDay,
18 MonthlyDate, Yearly }; 18 MonthlyDate, Yearly };
19 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08, 19 enum Days { MON = 0x01, TUE = 0x02, WED = 0x04, THU = 0x08,
20 FRI = 0x10, SAT = 0x20, SUN = 0x40 }; 20 FRI = 0x10, SAT = 0x20, SUN = 0x40 };
21 enum Fields{ RType = 0, RWeekdays, RPosition, RFreq, RHasEndDate, 21 enum Fields{ RType = 0, RWeekdays, RPosition, RFreq, RHasEndDate,
22 EndDate, Created, Exceptions }; 22 EndDate, Created, Exceptions };
23 23
24 ORecur(); 24 ORecur();
25 ORecur( const QMap<int, QString>& map );
25 ORecur( const ORecur& ); 26 ORecur( const ORecur& );
26 ~ORecur(); 27 ~ORecur();
27 28
28 ORecur &operator=( const ORecur& ); 29 ORecur &operator=( const ORecur& );
29 bool operator==(const ORecur& )const; 30 bool operator==(const ORecur& )const;
30 31
31 bool doesRecur()const; 32 bool doesRecur()const;
32 /* if it recurrs on that day */ 33 /* if it recurrs on that day */
33 bool doesRecur( const QDate& ); 34 bool doesRecur( const QDate& );
34 RepeatType type()const; 35 RepeatType type()const;
35 int frequency()const; 36 int frequency()const;
36 int position()const; 37 int position()const;
37 char days()const; 38 char days()const;
38 bool hasEndDate()const; 39 bool hasEndDate()const;
39 QDate start()const; 40 QDate start()const;
40 QDate endDate()const; 41 QDate endDate()const;
41 QDateTime createdDateTime()const; 42 QDateTime createdDateTime()const;
42 /** 43 /**
43 * starting on monday=0, sunday=6 44 * starting on monday=0, sunday=6
44 * for convience 45 * for convience
45 */ 46 */
46 bool repeatOnWeekDay( int day )const; 47 bool repeatOnWeekDay( int day )const;
47 48
48 /** 49 /**
49 * FromWhereToStart is not included!!! 50 * FromWhereToStart is not included!!!
50 */ 51 */
51 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate ); 52 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate );
52 53
53 /** 54 /**
54 * The module this ORecur belongs to 55 * The module this ORecur belongs to
55 */ 56 */
56 QString service()const; 57 QString service()const;
57 58
58 /* 59 /*
59 * reference to the exception list 60 * reference to the exception list
60 */ 61 */
61 ExceptionList &exceptions(); 62 ExceptionList &exceptions();
62 63
63 /** 64 /**
64 * the current repetition 65 * the current repetition
65 */ 66 */
66 int repetition()const; 67 int repetition()const;
67 68
68 void setType( const RepeatType& ); 69 void setType( const RepeatType& );
69 void setFrequency( int freq ); 70 void setFrequency( int freq );
70 void setPosition( int pos ); 71 void setPosition( int pos );
71 void setDays( char c); 72 void setDays( char c);
72 void setEndDate( const QDate& dt ); 73 void setEndDate( const QDate& dt );
73 void setStart( const QDate& dt ); 74 void setStart( const QDate& dt );
74 void setCreatedDateTime( const QDateTime& ); 75 void setCreatedDateTime( const QDateTime& );
75 void setHasEndDate( bool b ); 76 void setHasEndDate( bool b );
76 void setRepitition(int ); 77 void setRepitition(int );
77 78
78 void setService( const QString& ser ); 79 void setService( const QString& ser );
79 80
80 QMap<int, QString> toMap() const; 81 QMap<int, QString> toMap() const;
81 void fromMap( const QMap<int, QString>& map ); 82 void fromMap( const QMap<int, QString>& map );
82 83
83 /* almost internal */ 84 /* almost internal */
84 QString toString()const; 85 QString toString()const;
85private: 86private:
86 bool p_nextOccurrence( const QDate& from, QDate& next ); 87 bool p_nextOccurrence( const QDate& from, QDate& next );
87 void deref(); 88 void deref();
88 inline void checkOrModify(); 89 inline void checkOrModify();
89 90
90 /* Converts rType to String */ 91 /* Converts rType to String */
91 QString rTypeString() const; 92 QString rTypeString() const;
92 /* Returns a map to convert Stringname for RType to RepeatType */ 93 /* Returns a map to convert Stringname for RType to RepeatType */
93 QMap<QString, RepeatType> rTypeValueConvertMap() const; 94 QMap<QString, RepeatType> rTypeValueConvertMap() const;
94 95
95 class Data; 96 class Data;
96 Data* data; 97 Data* data;
97 class ORecurPrivate; 98 class ORecurPrivate;
98 ORecurPrivate *d; 99 ORecurPrivate *d;
99}; 100};
100 101
101#endif 102#endif
diff --git a/libopie2/opiepim/oevent.cpp b/libopie2/opiepim/oevent.cpp
index 7bcf944..c916297 100644
--- a/libopie2/opiepim/oevent.cpp
+++ b/libopie2/opiepim/oevent.cpp
@@ -1,577 +1,704 @@
1#include <qshared.h> 1#include <qshared.h>
2#include <qarray.h>
2 3
3#include <qpe/palmtopuidgen.h> 4#include <qpe/palmtopuidgen.h>
4#include <qpe/categories.h> 5#include <qpe/categories.h>
5#include <qpe/stringutil.h> 6#include <qpe/stringutil.h>
6 7
7#include "orecur.h" 8#include "orecur.h"
8#include "opimresolver.h" 9#include "opimresolver.h"
9#include "opimnotifymanager.h" 10#include "opimnotifymanager.h"
10 11
11#include "oevent.h" 12#include "oevent.h"
12 13
13int OCalendarHelper::week( const QDate& date) { 14int OCalendarHelper::week( const QDate& date) {
14 // Calculates the week this date is in within that 15 // Calculates the week this date is in within that
15 // month. Equals the "row" is is in in the month view 16 // month. Equals the "row" is is in in the month view
16 int week = 1; 17 int week = 1;
17 QDate tmp( date.year(), date.month(), 1 ); 18 QDate tmp( date.year(), date.month(), 1 );
18 if ( date.dayOfWeek() < tmp.dayOfWeek() ) 19 if ( date.dayOfWeek() < tmp.dayOfWeek() )
19 ++week; 20 ++week;
20 21
21 week += ( date.day() - 1 ) / 7; 22 week += ( date.day() - 1 ) / 7;
22 23
23 return week; 24 return week;
24} 25}
25int OCalendarHelper::ocurrence( const QDate& date) { 26int OCalendarHelper::ocurrence( const QDate& date) {
26 // calculates the number of occurrances of this day of the 27 // calculates the number of occurrances of this day of the
27 // week till the given date (e.g 3rd Wednesday of the month) 28 // week till the given date (e.g 3rd Wednesday of the month)
28 return ( date.day() - 1 ) / 7 + 1; 29 return ( date.day() - 1 ) / 7 + 1;
29} 30}
30int OCalendarHelper::dayOfWeek( char day ) { 31int OCalendarHelper::dayOfWeek( char day ) {
31 int dayOfWeek = 1; 32 int dayOfWeek = 1;
32 char i = ORecur::MON; 33 char i = ORecur::MON;
33 while ( !( i & day ) && i <= ORecur::SUN ) { 34 while ( !( i & day ) && i <= ORecur::SUN ) {
34 i <<= 1; 35 i <<= 1;
35 ++dayOfWeek; 36 ++dayOfWeek;
36 } 37 }
37 return dayOfWeek; 38 return dayOfWeek;
38} 39}
39int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) { 40int OCalendarHelper::monthDiff( const QDate& first, const QDate& second ) {
40 return ( second.year() - first.year() ) * 12 + 41 return ( second.year() - first.year() ) * 12 +
41 second.month() - first.month(); 42 second.month() - first.month();
42} 43}
43 44
44struct OEvent::Data : public QShared { 45struct OEvent::Data : public QShared {
45 Data() : QShared() { 46 Data() : QShared() {
46 child = 0; 47 child = 0;
47 recur = 0; 48 recur = 0;
48 manager = 0; 49 manager = 0;
49 isAllDay = false; 50 isAllDay = false;
50 parent = 0; 51 parent = 0;
51 } 52 }
52 ~Data() { 53 ~Data() {
53 delete manager; 54 delete manager;
54 delete recur; 55 delete recur;
55 } 56 }
56 QString description; 57 QString description;
57 QString location; 58 QString location;
58 OPimNotifyManager* manager; 59 OPimNotifyManager* manager;
59 ORecur* recur; 60 ORecur* recur;
60 QString note; 61 QString note;
61 QDateTime created; 62 QDateTime created;
62 QDateTime start; 63 QDateTime start;
63 QDateTime end; 64 QDateTime end;
64 bool isAllDay : 1; 65 bool isAllDay : 1;
65 QString timezone; 66 QString timezone;
66 QArray<int>* child; 67 QArray<int>* child;
67 int parent; 68 int parent;
68}; 69};
69 70
70OEvent::OEvent( int uid ) 71OEvent::OEvent( int uid )
71 : OPimRecord( uid ) { 72 : OPimRecord( uid ) {
72 data = new Data; 73 data = new Data;
73} 74}
74OEvent::OEvent( const OEvent& ev) 75OEvent::OEvent( const OEvent& ev)
75 : OPimRecord( ev ), data( ev.data ) 76 : OPimRecord( ev ), data( ev.data )
76{ 77{
77 data->ref(); 78 data->ref();
78} 79}
79OEvent::~OEvent() { 80OEvent::~OEvent() {
80 if ( data->deref() ) { 81 if ( data->deref() ) {
81 delete data; 82 delete data;
82 data = 0; 83 data = 0;
83 } 84 }
84} 85}
85OEvent& OEvent::operator=( const OEvent& ev) { 86OEvent& OEvent::operator=( const OEvent& ev) {
86 if ( this == &ev ) return *this; 87 if ( this == &ev ) return *this;
87 88
88 OPimRecord::operator=( ev ); 89 OPimRecord::operator=( ev );
89 ev.data->ref(); 90 ev.data->ref();
90 deref(); 91 deref();
91 data = ev.data; 92 data = ev.data;
92 93
93 94
94 return *this; 95 return *this;
95} 96}
96QString OEvent::description()const { 97QString OEvent::description()const {
97 return data->description; 98 return data->description;
98} 99}
99void OEvent::setDescription( const QString& description ) { 100void OEvent::setDescription( const QString& description ) {
100 changeOrModify(); 101 changeOrModify();
101 data->description = description; 102 data->description = description;
102} 103}
103void OEvent::setLocation( const QString& loc ) { 104void OEvent::setLocation( const QString& loc ) {
104 changeOrModify(); 105 changeOrModify();
105 data->location = loc; 106 data->location = loc;
106} 107}
107QString OEvent::location()const { 108QString OEvent::location()const {
108 return data->location; 109 return data->location;
109} 110}
110OPimNotifyManager &OEvent::notifiers()const { 111OPimNotifyManager &OEvent::notifiers()const {
111 // I hope we can skip the changeOrModify here 112 // I hope we can skip the changeOrModify here
112 // the notifier should take care of it 113 // the notifier should take care of it
113 // and OPimNotify is shared too 114 // and OPimNotify is shared too
114 if (!data->manager ) 115 if (!data->manager )
115 data->manager = new OPimNotifyManager; 116 data->manager = new OPimNotifyManager;
116 117
117 return *data->manager; 118 return *data->manager;
118} 119}
119bool OEvent::hasNotifiers()const { 120bool OEvent::hasNotifiers()const {
120 if (!data->manager ) 121 if (!data->manager )
121 return false; 122 return false;
122 if (data->manager->reminders().isEmpty() && 123 if (data->manager->reminders().isEmpty() &&
123 data->manager->alarms().isEmpty() ) 124 data->manager->alarms().isEmpty() )
124 return false; 125 return false;
125 126
126 return true; 127 return true;
127} 128}
128ORecur OEvent::recurrence()const { 129ORecur OEvent::recurrence()const {
129 if (!data->recur) 130 if (!data->recur)
130 data->recur = new ORecur; 131 data->recur = new ORecur;
131 132
132 return *data->recur; 133 return *data->recur;
133} 134}
134void OEvent::setRecurrence( const ORecur& rec) { 135void OEvent::setRecurrence( const ORecur& rec) {
135 changeOrModify(); 136 changeOrModify();
136 if (data->recur ) 137 if (data->recur )
137 (*data->recur) = rec; 138 (*data->recur) = rec;
138 else 139 else
139 data->recur = new ORecur( rec ); 140 data->recur = new ORecur( rec );
140} 141}
141bool OEvent::hasRecurrence()const { 142bool OEvent::hasRecurrence()const {
142 if (!data->recur ) return false; 143 if (!data->recur ) return false;
143 return data->recur->doesRecur(); 144 return data->recur->doesRecur();
144} 145}
145QString OEvent::note()const { 146QString OEvent::note()const {
146 return data->note; 147 return data->note;
147} 148}
148void OEvent::setNote( const QString& note ) { 149void OEvent::setNote( const QString& note ) {
149 changeOrModify(); 150 changeOrModify();
150 data->note = note; 151 data->note = note;
151} 152}
152QDateTime OEvent::createdDateTime()const { 153QDateTime OEvent::createdDateTime()const {
153 return data->created; 154 return data->created;
154} 155}
155void OEvent::setCreatedDateTime( const QDateTime& time ) { 156void OEvent::setCreatedDateTime( const QDateTime& time ) {
156 changeOrModify(); 157 changeOrModify();
157 data->created = time; 158 data->created = time;
158} 159}
159QDateTime OEvent::startDateTime()const { 160QDateTime OEvent::startDateTime()const {
160 if ( data->isAllDay ) 161 if ( data->isAllDay )
161 return QDateTime( data->start.date(), QTime(0, 0, 0 ) ); 162 return QDateTime( data->start.date(), QTime(0, 0, 0 ) );
162 return data->start; 163 return data->start;
163} 164}
164QDateTime OEvent::startDateTimeInZone()const { 165QDateTime OEvent::startDateTimeInZone()const {
165 /* if no timezone, or all day event or if the current and this timeZone match... */ 166 /* if no timezone, or all day event or if the current and this timeZone match... */
166 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime(); 167 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime();
167 168
168 OTimeZone zone(data->timezone ); 169 OTimeZone zone(data->timezone );
169 return zone.toDateTime( data->start, OTimeZone::current() ); 170 return zone.toDateTime( data->start, OTimeZone::current() );
170} 171}
171void OEvent::setStartDateTime( const QDateTime& dt ) { 172void OEvent::setStartDateTime( const QDateTime& dt ) {
172 changeOrModify(); 173 changeOrModify();
173 data->start = dt; 174 data->start = dt;
174} 175}
175QDateTime OEvent::endDateTime()const { 176QDateTime OEvent::endDateTime()const {
176 /* 177 /*
177 * if all Day event the end time needs 178 * if all Day event the end time needs
178 * to be on the same day as the start 179 * to be on the same day as the start
179 */ 180 */
180 if ( data->isAllDay ) 181 if ( data->isAllDay )
181 return QDateTime( data->start.date(), QTime(23, 59, 59 ) ); 182 return QDateTime( data->start.date(), QTime(23, 59, 59 ) );
182 return data->end; 183 return data->end;
183} 184}
184QDateTime OEvent::endDateTimeInZone()const { 185QDateTime OEvent::endDateTimeInZone()const {
185 /* if no timezone, or all day event or if the current and this timeZone match... */ 186 /* if no timezone, or all day event or if the current and this timeZone match... */
186 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime(); 187 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime();
187 188
188 OTimeZone zone(data->timezone ); 189 OTimeZone zone(data->timezone );
189 return zone.toDateTime( data->end, OTimeZone::current() ); 190 return zone.toDateTime( data->end, OTimeZone::current() );
190} 191}
191void OEvent::setEndDateTime( const QDateTime& dt ) { 192void OEvent::setEndDateTime( const QDateTime& dt ) {
192 changeOrModify(); 193 changeOrModify();
193 data->end = dt; 194 data->end = dt;
194} 195}
195bool OEvent::isMultipleDay()const { 196bool OEvent::isMultipleDay()const {
196 return data->end.date().day() - data->start.date().day(); 197 return data->end.date().day() - data->start.date().day();
197} 198}
198bool OEvent::isAllDay()const { 199bool OEvent::isAllDay()const {
199 return data->isAllDay; 200 return data->isAllDay;
200} 201}
201void OEvent::setAllDay( bool allDay ) { 202void OEvent::setAllDay( bool allDay ) {
202 changeOrModify(); 203 changeOrModify();
203 data->isAllDay = allDay; 204 data->isAllDay = allDay;
204 if (allDay ) data->timezone = "UTC"; 205 if (allDay ) data->timezone = "UTC";
205} 206}
206void OEvent::setTimeZone( const QString& tz ) { 207void OEvent::setTimeZone( const QString& tz ) {
207 changeOrModify(); 208 changeOrModify();
208 data->timezone = tz; 209 data->timezone = tz;
209} 210}
210QString OEvent::timeZone()const { 211QString OEvent::timeZone()const {
211 if (data->isAllDay ) return QString::fromLatin1("UTC"); 212 if (data->isAllDay ) return QString::fromLatin1("UTC");
212 return data->timezone; 213 return data->timezone;
213} 214}
214bool OEvent::match( const QRegExp& re )const { 215bool OEvent::match( const QRegExp& re )const {
215 if ( re.match( data->description ) != -1 ){ 216 if ( re.match( data->description ) != -1 ){
216 setLastHitField( Qtopia::DatebookDescription ); 217 setLastHitField( Qtopia::DatebookDescription );
217 return true; 218 return true;
218 } 219 }
219 if ( re.match( data->note ) != -1 ){ 220 if ( re.match( data->note ) != -1 ){
220 setLastHitField( Qtopia::Note ); 221 setLastHitField( Qtopia::Note );
221 return true; 222 return true;
222 } 223 }
223 if ( re.match( data->location ) != -1 ){ 224 if ( re.match( data->location ) != -1 ){
224 setLastHitField( Qtopia::Location ); 225 setLastHitField( Qtopia::Location );
225 return true; 226 return true;
226 } 227 }
227 if ( re.match( data->start.toString() ) != -1 ){ 228 if ( re.match( data->start.toString() ) != -1 ){
228 setLastHitField( Qtopia::StartDateTime ); 229 setLastHitField( Qtopia::StartDateTime );
229 return true; 230 return true;
230 } 231 }
231 if ( re.match( data->end.toString() ) != -1 ){ 232 if ( re.match( data->end.toString() ) != -1 ){
232 setLastHitField( Qtopia::EndDateTime ); 233 setLastHitField( Qtopia::EndDateTime );
233 return true; 234 return true;
234 } 235 }
235 return false; 236 return false;
236} 237}
237QString OEvent::toRichText()const { 238QString OEvent::toRichText()const {
238 QString text, value; 239 QString text, value;
239 240
240 // description 241 // description
241 text += "<b><h3><img src=\"datebook/DateBook\">"; 242 text += "<b><h3><img src=\"datebook/DateBook\">";
242 if ( !description().isEmpty() ) { 243 if ( !description().isEmpty() ) {
243 text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "" ); 244 text += Qtopia::escapeString(description() ).replace(QRegExp( "[\n]"), "" );
244 } 245 }
245 text += "</h3></b><br><hr><br>"; 246 text += "</h3></b><br><hr><br>";
246 247
247 // location 248 // location
248 if ( !(value = location()).isEmpty() ) { 249 if ( !(value = location()).isEmpty() ) {
249 text += "<b>" + QObject::tr( "Location:" ) + "</b> "; 250 text += "<b>" + QObject::tr( "Location:" ) + "</b> ";
250 text += Qtopia::escapeString(value) + "<br>"; 251 text += Qtopia::escapeString(value) + "<br>";
251 } 252 }
252 253
253 // all day event 254 // all day event
254 if ( isAllDay() ) { 255 if ( isAllDay() ) {
255 text += "<b><i>" + QObject::tr( "This is an all day event" ) + "</i></b><br>"; 256 text += "<b><i>" + QObject::tr( "This is an all day event" ) + "</i></b><br>";
256 } 257 }
257 // multiple day event 258 // multiple day event
258 else if ( isMultipleDay () ) { 259 else if ( isMultipleDay () ) {
259 text += "<b><i>" + QObject::tr( "This is a multiple day event" ) + "</i></b><br>"; 260 text += "<b><i>" + QObject::tr( "This is a multiple day event" ) + "</i></b><br>";
260 } 261 }
261 // start & end times 262 // start & end times
262 else { 263 else {
263 // start time 264 // start time
264 if ( startDateTime().isValid() ) { 265 if ( startDateTime().isValid() ) {
265 text += "<b>" + QObject::tr( "Start:") + "</b> "; 266 text += "<b>" + QObject::tr( "Start:") + "</b> ";
266 text += Qtopia::escapeString(startDateTime().toString() ). 267 text += Qtopia::escapeString(startDateTime().toString() ).
267 replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; 268 replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
268 } 269 }
269 270
270 // end time 271 // end time
271 if ( endDateTime().isValid() ) { 272 if ( endDateTime().isValid() ) {
272 text += "<b>" + QObject::tr( "End:") + "</b> "; 273 text += "<b>" + QObject::tr( "End:") + "</b> ";
273 text += Qtopia::escapeString(endDateTime().toString() ). 274 text += Qtopia::escapeString(endDateTime().toString() ).
274 replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; 275 replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
275 } 276 }
276 } 277 }
277 278
278 // categories 279 // categories
279 if ( categoryNames("Calendar").count() ){ 280 if ( categoryNames("Calendar").count() ){
280 text += "<b>" + QObject::tr( "Category:") + "</b> "; 281 text += "<b>" + QObject::tr( "Category:") + "</b> ";
281 text += categoryNames("Calendar").join(", "); 282 text += categoryNames("Calendar").join(", ");
282 text += "<br>"; 283 text += "<br>";
283 } 284 }
284 285
285 //notes 286 //notes
286 if ( !note().isEmpty() ) { 287 if ( !note().isEmpty() ) {
287 text += "<b>" + QObject::tr( "Note:") + "</b><br>"; 288 text += "<b>" + QObject::tr( "Note:") + "</b><br>";
288 text += note(); 289 text += note();
289// text += Qtopia::escapeString(note() ). 290// text += Qtopia::escapeString(note() ).
290// replace(QRegExp( "[\n]"), "<br>" ) + "<br>"; 291// replace(QRegExp( "[\n]"), "<br>" ) + "<br>";
291 } 292 }
292 return text; 293 return text;
293} 294}
294QString OEvent::toShortText()const { 295QString OEvent::toShortText()const {
295 QString text; 296 QString text;
296 text += QString::number( startDateTime().date().day() ); 297 text += QString::number( startDateTime().date().day() );
297 text += "."; 298 text += ".";
298 text += QString::number( startDateTime().date().month() ); 299 text += QString::number( startDateTime().date().month() );
299 text += "."; 300 text += ".";
300 text += QString::number( startDateTime().date().year() ); 301 text += QString::number( startDateTime().date().year() );
301 text += " "; 302 text += " ";
302 text += QString::number( startDateTime().time().hour() ); 303 text += QString::number( startDateTime().time().hour() );
303 text += ":"; 304 text += ":";
304 text += QString::number( startDateTime().time().minute() ); 305 text += QString::number( startDateTime().time().minute() );
305 text += " - "; 306 text += " - ";
306 text += description(); 307 text += description();
307 return text; 308 return text;
308} 309}
309QString OEvent::type()const { 310QString OEvent::type()const {
310 return QString::fromLatin1("OEvent"); 311 return QString::fromLatin1("OEvent");
311} 312}
312QString OEvent::recordField( int /*id */ )const { 313QString OEvent::recordField( int /*id */ )const {
313 return QString::null; 314 return QString::null;
314} 315}
315int OEvent::rtti() { 316int OEvent::rtti() {
316 return OPimResolver::DateBook; 317 return OPimResolver::DateBook;
317} 318}
318bool OEvent::loadFromStream( QDataStream& ) { 319bool OEvent::loadFromStream( QDataStream& ) {
319 return true; 320 return true;
320} 321}
321bool OEvent::saveToStream( QDataStream& )const { 322bool OEvent::saveToStream( QDataStream& )const {
322 return true; 323 return true;
323} 324}
324void OEvent::changeOrModify() { 325void OEvent::changeOrModify() {
325 if ( data->count != 1 ) { 326 if ( data->count != 1 ) {
326 data->deref(); 327 data->deref();
327 Data* d2 = new Data; 328 Data* d2 = new Data;
328 d2->description = data->description; 329 d2->description = data->description;
329 d2->location = data->location; 330 d2->location = data->location;
330 331
331 if (data->manager ) 332 if (data->manager )
332 d2->manager = new OPimNotifyManager( *data->manager ); 333 d2->manager = new OPimNotifyManager( *data->manager );
333 334
334 if ( data->recur ) 335 if ( data->recur )
335 d2->recur = new ORecur( *data->recur ); 336 d2->recur = new ORecur( *data->recur );
336 337
337 d2->note = data->note; 338 d2->note = data->note;
338 d2->created = data->created; 339 d2->created = data->created;
339 d2->start = data->start; 340 d2->start = data->start;
340 d2->end = data->end; 341 d2->end = data->end;
341 d2->isAllDay = data->isAllDay; 342 d2->isAllDay = data->isAllDay;
342 d2->timezone = data->timezone; 343 d2->timezone = data->timezone;
343 d2->parent = data->parent; 344 d2->parent = data->parent;
344 345
345 if ( data->child ) { 346 if ( data->child ) {
346 d2->child = new QArray<int>( *data->child ); 347 d2->child = new QArray<int>( *data->child );
347 d2->child->detach(); 348 d2->child->detach();
348 } 349 }
349 350
350 data = d2; 351 data = d2;
351 } 352 }
352} 353}
353void OEvent::deref() { 354void OEvent::deref() {
354 if ( data->deref() ) { 355 if ( data->deref() ) {
355 delete data; 356 delete data;
356 data = 0; 357 data = 0;
357 } 358 }
358} 359}
359// FIXME 360// Exporting Event data to map. Using the same
361// encoding as ODateBookAccessBackend_xml does..
362// Thus, we could remove the stuff there and use this
363// for it and for all other places..
364// Encoding should happen at one place, only ! (eilers)
360QMap<int, QString> OEvent::toMap()const { 365QMap<int, QString> OEvent::toMap()const {
361 return QMap<int, QString>(); 366 QMap<int, QString> retMap;
367
368 retMap.insert( OEvent::FUid, QString::number( uid() ) );
369 retMap.insert( OEvent::FCategories, Qtopia::escapeString( Qtopia::Record::idsToString( categories() ) ));
370 retMap.insert( OEvent::FDescription, Qtopia::escapeString( description() ) );
371 retMap.insert( OEvent::FLocation, Qtopia::escapeString( location() ) );
372 retMap.insert( OEvent::FType, isAllDay() ? "AllDay" : "" );
373 OPimAlarm alarm = notifiers().alarms()[0];
374 retMap.insert( OEvent::FAlarm, QString::number( alarm.dateTime().secsTo( startDateTime() ) / 60 ) );
375 retMap.insert( OEvent::FSound, (alarm.sound() == OPimAlarm::Loud) ? "loud" : "silent" );
376
377 OTimeZone zone( timeZone().isEmpty() ? OTimeZone::current() : timeZone() );
378 retMap.insert( OEvent::FStart, QString::number( zone.fromUTCDateTime( zone.toDateTime( startDateTime(), OTimeZone::utc() ) ) ) );
379 retMap.insert( OEvent::FEnd, QString::number( zone.fromUTCDateTime( zone.toDateTime( endDateTime(), OTimeZone::utc() ) ) ) );
380 retMap.insert( OEvent::FNote, Qtopia::escapeString( note() ) );
381 retMap.insert( OEvent::FTimeZone, timeZone().isEmpty() ? "None" : timeZone() );
382 if( parent() )
383 retMap.insert( OEvent::FRecParent, QString::number( parent() ) );
384 if( children().count() ){
385 QArray<int> childr = children();
386 QString buf;
387 for ( uint i = 0; i < childr.count(); i++ ) {
388 if ( i != 0 ) buf += " ";
389 buf += QString::number( childr[i] );
390 }
391 retMap.insert( OEvent::FRecChildren, buf );
392 }
393
394 // Add recurrence stuff
395 if( hasRecurrence() ){
396 ORecur recur = recurrence();
397 QMap<int, QString> recFields = recur.toMap();
398 retMap.insert( OEvent::FRType, recFields[ORecur::RType] );
399 retMap.insert( OEvent::FRWeekdays, recFields[ORecur::RWeekdays] );
400 retMap.insert( OEvent::FRPosition, recFields[ORecur::RPosition] );
401 retMap.insert( OEvent::FRFreq, recFields[ORecur::RFreq] );
402 retMap.insert( OEvent::FRHasEndDate, recFields[ORecur::RHasEndDate] );
403 retMap.insert( OEvent::FREndDate, recFields[ORecur::EndDate] );
404 retMap.insert( OEvent::FRCreated, recFields[ORecur::Created] );
405 retMap.insert( OEvent::FRExceptions, recFields[ORecur::Exceptions] );
406 }
407
408 return retMap;
409}
410
411void OEvent::fromMap( const QMap<int, QString>& map )
412{
413
414 // We just want to set the UID if it is really stored.
415 if ( !map[OEvent::FUid].isEmpty() )
416 setUid( map[OEvent::FUid].toInt() );
417
418 setCategories( idsFromString( map[OEvent::FCategories] ) );
419 setDescription( map[OEvent::FDescription] );
420 setLocation( map[OEvent::FLocation] );
421
422 if ( map[OEvent::FType] == "AllDay" )
423 setAllDay( true );
424 else
425 setAllDay( false );
426
427 int alarmTime = -1;
428 if( !map[OEvent::FAlarm].isEmpty() )
429 alarmTime = map[OEvent::FAlarm].toInt();
430
431 int sound = ( ( map[OEvent::FSound] == "loud" ) ? OPimAlarm::Loud : OPimAlarm::Silent );
432 if ( ( alarmTime != -1 ) ){
433 QDateTime dt = startDateTime().addSecs( -1*alarmTime*60 );
434 OPimAlarm al( sound , dt );
435 notifiers().add( al );
436 }
437 if ( !map[OEvent::FTimeZone].isEmpty() && ( map[OEvent::FTimeZone] != "None" ) ){
438 setTimeZone( map[OEvent::FTimeZone] );
439 }
440
441 time_t start = (time_t) map[OEvent::FStart].toLong();
442 time_t end = (time_t) map[OEvent::FEnd].toLong();
443
444 /* AllDay is always in UTC */
445 if ( isAllDay() ) {
446 OTimeZone utc = OTimeZone::utc();
447 setStartDateTime( utc.fromUTCDateTime( start ) );
448 setEndDateTime ( utc.fromUTCDateTime( end ) );
449 setTimeZone( "UTC"); // make sure it is really utc
450 }else {
451 /* to current date time */
452 // qWarning(" Start is %d", start );
453 OTimeZone zone( timeZone().isEmpty() ? OTimeZone::current() : timeZone() );
454 QDateTime date = zone.toDateTime( start );
455 qWarning(" Start is %s", date.toString().latin1() );
456 setStartDateTime( zone.toDateTime( date, OTimeZone::current() ) );
457
458 date = zone.toDateTime( end );
459 setEndDateTime ( zone.toDateTime( date, OTimeZone::current() ) );
460 }
461
462 if ( !map[OEvent::FRecParent].isEmpty() )
463 setParent( map[OEvent::FRecParent].toInt() );
464
465 if ( !map[OEvent::FRecChildren].isEmpty() ){
466 QStringList list = QStringList::split(' ', map[OEvent::FRecChildren] );
467 for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
468 addChild( (*it).toInt() );
469 }
470 }
471
472 // Fill recurrence stuff and put it directly into the ORecur-Object using fromMap..
473 if( !map[OEvent::FRType].isEmpty() ){
474 QMap<int, QString> recFields;
475 recFields.insert( ORecur::RType, map[OEvent::FRType] );
476 recFields.insert( ORecur::RWeekdays, map[OEvent::FRWeekdays] );
477 recFields.insert( ORecur::RPosition, map[OEvent::FRPosition] );
478 recFields.insert( ORecur::RFreq, map[OEvent::FRFreq] );
479 recFields.insert( ORecur::RHasEndDate, map[OEvent::FRHasEndDate] );
480 recFields.insert( ORecur::EndDate, map[OEvent::FREndDate] );
481 recFields.insert( ORecur::Created, map[OEvent::FRCreated] );
482 recFields.insert( ORecur::Exceptions, map[OEvent::FRExceptions] );
483 ORecur recur( recFields );
484 setRecurrence( recur );
485 }
486
362} 487}
488
489
363int OEvent::parent()const { 490int OEvent::parent()const {
364 return data->parent; 491 return data->parent;
365} 492}
366void OEvent::setParent( int uid ) { 493void OEvent::setParent( int uid ) {
367 changeOrModify(); 494 changeOrModify();
368 data->parent = uid; 495 data->parent = uid;
369} 496}
370QArray<int> OEvent::children() const{ 497QArray<int> OEvent::children() const{
371 if (!data->child) return QArray<int>(); 498 if (!data->child) return QArray<int>();
372 else 499 else
373 return data->child->copy(); 500 return data->child->copy();
374} 501}
375void OEvent::setChildren( const QArray<int>& arr ) { 502void OEvent::setChildren( const QArray<int>& arr ) {
376 changeOrModify(); 503 changeOrModify();
377 if (data->child) delete data->child; 504 if (data->child) delete data->child;
378 505
379 data->child = new QArray<int>( arr ); 506 data->child = new QArray<int>( arr );
380 data->child->detach(); 507 data->child->detach();
381} 508}
382void OEvent::addChild( int uid ) { 509void OEvent::addChild( int uid ) {
383 changeOrModify(); 510 changeOrModify();
384 if (!data->child ) { 511 if (!data->child ) {
385 data->child = new QArray<int>(1); 512 data->child = new QArray<int>(1);
386 (*data->child)[0] = uid; 513 (*data->child)[0] = uid;
387 }else{ 514 }else{
388 int count = data->child->count(); 515 int count = data->child->count();
389 data->child->resize( count + 1 ); 516 data->child->resize( count + 1 );
390 (*data->child)[count] = uid; 517 (*data->child)[count] = uid;
391 } 518 }
392} 519}
393void OEvent::removeChild( int uid ) { 520void OEvent::removeChild( int uid ) {
394 if (!data->child || !data->child->contains( uid ) ) return; 521 if (!data->child || !data->child->contains( uid ) ) return;
395 changeOrModify(); 522 changeOrModify();
396 QArray<int> newAr( data->child->count() - 1 ); 523 QArray<int> newAr( data->child->count() - 1 );
397 int j = 0; 524 int j = 0;
398 uint count = data->child->count(); 525 uint count = data->child->count();
399 for ( uint i = 0; i < count; i++ ) { 526 for ( uint i = 0; i < count; i++ ) {
400 if ( (*data->child)[i] != uid ) { 527 if ( (*data->child)[i] != uid ) {
401 newAr[j] = (*data->child)[i]; 528 newAr[j] = (*data->child)[i];
402 j++; 529 j++;
403 } 530 }
404 } 531 }
405 (*data->child) = newAr; 532 (*data->child) = newAr;
406} 533}
407struct OEffectiveEvent::Data : public QShared { 534struct OEffectiveEvent::Data : public QShared {
408 Data() : QShared() { 535 Data() : QShared() {
409 } 536 }
410 OEvent event; 537 OEvent event;
411 QDate date; 538 QDate date;
412 QTime start, end; 539 QTime start, end;
413 QDate startDate, endDate; 540 QDate startDate, endDate;
414 bool dates : 1; 541 bool dates : 1;
415}; 542};
416 543
417OEffectiveEvent::OEffectiveEvent() { 544OEffectiveEvent::OEffectiveEvent() {
418 data = new Data; 545 data = new Data;
419 data->date = QDate::currentDate(); 546 data->date = QDate::currentDate();
420 data->start = data->end = QTime::currentTime(); 547 data->start = data->end = QTime::currentTime();
421 data->dates = false; 548 data->dates = false;
422} 549}
423OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate, 550OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate,
424 Position pos ) { 551 Position pos ) {
425 data = new Data; 552 data = new Data;
426 data->event = ev; 553 data->event = ev;
427 data->date = startDate; 554 data->date = startDate;
428 if ( pos & Start ) 555 if ( pos & Start )
429 data->start = ev.startDateTime().time(); 556 data->start = ev.startDateTime().time();
430 else 557 else
431 data->start = QTime( 0, 0, 0 ); 558 data->start = QTime( 0, 0, 0 );
432 559
433 if ( pos & End ) 560 if ( pos & End )
434 data->end = ev.endDateTime().time(); 561 data->end = ev.endDateTime().time();
435 else 562 else
436 data->end = QTime( 23, 59, 59 ); 563 data->end = QTime( 23, 59, 59 );
437 564
438 data->dates = false; 565 data->dates = false;
439} 566}
440OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) { 567OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) {
441 data = ev.data; 568 data = ev.data;
442 data->ref(); 569 data->ref();
443} 570}
444OEffectiveEvent::~OEffectiveEvent() { 571OEffectiveEvent::~OEffectiveEvent() {
445 if ( data->deref() ) { 572 if ( data->deref() ) {
446 delete data; 573 delete data;
447 data = 0; 574 data = 0;
448 } 575 }
449} 576}
450OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) { 577OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) {
451 if ( *this == ev ) return *this; 578 if ( *this == ev ) return *this;
452 579
453 ev.data->ref(); 580 ev.data->ref();
454 deref(); 581 deref();
455 data = ev.data; 582 data = ev.data;
456 583
457 return *this; 584 return *this;
458} 585}
459 586
460void OEffectiveEvent::setStartTime( const QTime& ti) { 587void OEffectiveEvent::setStartTime( const QTime& ti) {
461 changeOrModify(); 588 changeOrModify();
462 data->start = ti; 589 data->start = ti;
463} 590}
464void OEffectiveEvent::setEndTime( const QTime& en) { 591void OEffectiveEvent::setEndTime( const QTime& en) {
465 changeOrModify(); 592 changeOrModify();
466 data->end = en; 593 data->end = en;
467} 594}
468void OEffectiveEvent::setEvent( const OEvent& ev) { 595void OEffectiveEvent::setEvent( const OEvent& ev) {
469 changeOrModify(); 596 changeOrModify();
470 data->event = ev; 597 data->event = ev;
471} 598}
472void OEffectiveEvent::setDate( const QDate& da) { 599void OEffectiveEvent::setDate( const QDate& da) {
473 changeOrModify(); 600 changeOrModify();
474 data->date = da; 601 data->date = da;
475} 602}
476void OEffectiveEvent::setEffectiveDates( const QDate& from, 603void OEffectiveEvent::setEffectiveDates( const QDate& from,
477 const QDate& to ) { 604 const QDate& to ) {
478 if (!from.isValid() ) { 605 if (!from.isValid() ) {
479 data->dates = false; 606 data->dates = false;
480 return; 607 return;
481 } 608 }
482 609
483 data->startDate = from; 610 data->startDate = from;
484 data->endDate = to; 611 data->endDate = to;
485} 612}
486QString OEffectiveEvent::description()const { 613QString OEffectiveEvent::description()const {
487 return data->event.description(); 614 return data->event.description();
488} 615}
489QString OEffectiveEvent::location()const { 616QString OEffectiveEvent::location()const {
490 return data->event.location(); 617 return data->event.location();
491} 618}
492QString OEffectiveEvent::note()const { 619QString OEffectiveEvent::note()const {
493 return data->event.note(); 620 return data->event.note();
494} 621}
495OEvent OEffectiveEvent::event()const { 622OEvent OEffectiveEvent::event()const {
496 return data->event; 623 return data->event;
497} 624}
498QTime OEffectiveEvent::startTime()const { 625QTime OEffectiveEvent::startTime()const {
499 return data->start; 626 return data->start;
500} 627}
501QTime OEffectiveEvent::endTime()const { 628QTime OEffectiveEvent::endTime()const {
502 return data->end; 629 return data->end;
503} 630}
504QDate OEffectiveEvent::date()const { 631QDate OEffectiveEvent::date()const {
505 return data->date; 632 return data->date;
506} 633}
507int OEffectiveEvent::length()const { 634int OEffectiveEvent::length()const {
508 return (data->end.hour() * 60 - data->start.hour() * 60) 635 return (data->end.hour() * 60 - data->start.hour() * 60)
509 + QABS(data->start.minute() - data->end.minute() ); 636 + QABS(data->start.minute() - data->end.minute() );
510} 637}
511int OEffectiveEvent::size()const { 638int OEffectiveEvent::size()const {
512 return ( data->end.hour() - data->start.hour() ) * 3600 639 return ( data->end.hour() - data->start.hour() ) * 3600
513 + (data->end.minute() - data->start.minute() * 60 640 + (data->end.minute() - data->start.minute() * 60
514 + data->end.second() - data->start.second() ); 641 + data->end.second() - data->start.second() );
515} 642}
516QDate OEffectiveEvent::startDate()const { 643QDate OEffectiveEvent::startDate()const {
517 if ( data->dates ) 644 if ( data->dates )
518 return data->startDate; 645 return data->startDate;
519 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer 646 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer
520 return data->date; 647 return data->date;
521 else 648 else
522 return data->event.startDateTime().date(); 649 return data->event.startDateTime().date();
523} 650}
524QDate OEffectiveEvent::endDate()const { 651QDate OEffectiveEvent::endDate()const {
525 if ( data->dates ) 652 if ( data->dates )
526 return data->endDate; 653 return data->endDate;
527 else if ( data->event.hasRecurrence() ) 654 else if ( data->event.hasRecurrence() )
528 return data->date; 655 return data->date;
529 else 656 else
530 return data->event.endDateTime().date(); 657 return data->event.endDateTime().date();
531} 658}
532void OEffectiveEvent::deref() { 659void OEffectiveEvent::deref() {
533 if ( data->deref() ) { 660 if ( data->deref() ) {
534 delete data; 661 delete data;
535 data = 0; 662 data = 0;
536 } 663 }
537} 664}
538void OEffectiveEvent::changeOrModify() { 665void OEffectiveEvent::changeOrModify() {
539 if ( data->count != 1 ) { 666 if ( data->count != 1 ) {
540 data->deref(); 667 data->deref();
541 Data* d2 = new Data; 668 Data* d2 = new Data;
542 d2->event = data->event; 669 d2->event = data->event;
543 d2->date = data->date; 670 d2->date = data->date;
544 d2->start = data->start; 671 d2->start = data->start;
545 d2->end = data->end; 672 d2->end = data->end;
546 d2->startDate = data->startDate; 673 d2->startDate = data->startDate;
547 d2->endDate = data->endDate; 674 d2->endDate = data->endDate;
548 d2->dates = data->dates; 675 d2->dates = data->dates;
549 data = d2; 676 data = d2;
550 } 677 }
551} 678}
552bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{ 679bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{
553 if ( data->date < e.date() ) 680 if ( data->date < e.date() )
554 return TRUE; 681 return TRUE;
555 if ( data->date == e.date() ) 682 if ( data->date == e.date() )
556 return ( startTime() < e.startTime() ); 683 return ( startTime() < e.startTime() );
557 else 684 else
558 return FALSE; 685 return FALSE;
559} 686}
560bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{ 687bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{
561 return (data->date <= e.date() ); 688 return (data->date <= e.date() );
562} 689}
563bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const { 690bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const {
564 return ( date() == e.date() 691 return ( date() == e.date()
565 && startTime() == e.startTime() 692 && startTime() == e.startTime()
566 && endTime()== e.endTime() 693 && endTime()== e.endTime()
567 && event() == e.event() ); 694 && event() == e.event() );
568} 695}
569bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const { 696bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const {
570 return !(*this == e ); 697 return !(*this == e );
571} 698}
572bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const { 699bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const {
573 return !(*this <= e ); 700 return !(*this <= e );
574} 701}
575bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const { 702bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const {
576 return !(*this < e); 703 return !(*this < e);
577} 704}
diff --git a/libopie2/opiepim/oevent.h b/libopie2/opiepim/oevent.h
index 30f442e..9218c97 100644
--- a/libopie2/opiepim/oevent.h
+++ b/libopie2/opiepim/oevent.h
@@ -1,220 +1,230 @@
1// CONTAINS GPLed code of TT 1// CONTAINS GPLed code of TT
2 2
3#ifndef OPIE_PIM_EVENT_H 3#ifndef OPIE_PIM_EVENT_H
4#define OPIE_PIM_EVENT_H 4#define OPIE_PIM_EVENT_H
5 5
6#include <qstring.h> 6#include <qstring.h>
7#include <qdatetime.h> 7#include <qdatetime.h>
8#include <qvaluelist.h> 8#include <qvaluelist.h>
9 9
10#include <qpe/recordfields.h> 10#include <qpe/recordfields.h>
11#include <qpe/palmtopuidgen.h> 11#include <qpe/palmtopuidgen.h>
12 12
13#include "otimezone.h" 13#include "otimezone.h"
14#include "opimrecord.h" 14#include "opimrecord.h"
15 15
16struct OCalendarHelper { 16struct OCalendarHelper {
17 /** calculate the week number of the date */ 17 /** calculate the week number of the date */
18 static int week( const QDate& ); 18 static int week( const QDate& );
19 /** calculate the occurence of week days since the start of the month */ 19 /** calculate the occurence of week days since the start of the month */
20 static int ocurrence( const QDate& ); 20 static int ocurrence( const QDate& );
21 21
22 // returns the dayOfWeek for the *first* day it finds (ignores 22 // returns the dayOfWeek for the *first* day it finds (ignores
23 // any further days!). Returns 1 (Monday) if there isn't any day found 23 // any further days!). Returns 1 (Monday) if there isn't any day found
24 static int dayOfWeek( char day ); 24 static int dayOfWeek( char day );
25 25
26 /** returns the diff of month */ 26 /** returns the diff of month */
27 static int monthDiff( const QDate& first, const QDate& second ); 27 static int monthDiff( const QDate& first, const QDate& second );
28 28
29}; 29};
30 30
31class OPimNotifyManager; 31class OPimNotifyManager;
32class ORecur; 32class ORecur;
33 33
34/** 34/**
35 * This is the container for all Events. It encapsules all 35 * This is the container for all Events. It encapsules all
36 * available information for a single Event 36 * available information for a single Event
37 * @short container for events. 37 * @short container for events.
38 */ 38 */
39class OEvent : public OPimRecord { 39class OEvent : public OPimRecord {
40public: 40public:
41 typedef QValueList<OEvent> ValueList; 41 typedef QValueList<OEvent> ValueList;
42 /** 42 /**
43 * RecordFields contain possible attributes 43 * RecordFields contain possible attributes
44 * used in the Results of toMap()..
44 */ 45 */
45 enum RecordFields { 46 enum RecordFields {
46 Uid = Qtopia::UID_ID, 47 FUid = Qtopia::UID_ID,
47 Category = Qtopia::CATEGORY_ID, 48 FCategories = Qtopia::CATEGORY_ID,
48 Description, 49 FDescription = 0,
49 Location, 50 FLocation,
50 Alarm, 51 FType,
51 Reminder, 52 FAlarm,
52 Recurrence, 53 FSound,
53 Note, 54 FRType,
54 Created, 55 FRWeekdays,
55 StartDate, 56 FRPosition,
56 EndDate, 57 FRFreq,
57 AllDay, 58 FRHasEndDate,
58 TimeZone 59 FREndDate,
60 FRCreated,
61 FRExceptions,
62 FStart,
63 FEnd,
64 FNote,
65 FTimeZone,
66 FRecParent,
67 FRecChildren,
59 }; 68 };
60 69
61 /** 70 /**
62 * Start with an Empty OEvent. UID == 0 means that it is empty 71 * Start with an Empty OEvent. UID == 0 means that it is empty
63 */ 72 */
64 OEvent(int uid = 0); 73 OEvent(int uid = 0);
65 74
66 /** 75 /**
67 * copy c'tor 76 * copy c'tor
68 */ 77 */
69 OEvent( const OEvent& ); 78 OEvent( const OEvent& );
70 ~OEvent(); 79 ~OEvent();
71 OEvent &operator=( const OEvent& ); 80 OEvent &operator=( const OEvent& );
72 81
73 QString description()const; 82 QString description()const;
74 void setDescription( const QString& description ); 83 void setDescription( const QString& description );
75 84
76 QString location()const; 85 QString location()const;
77 void setLocation( const QString& loc ); 86 void setLocation( const QString& loc );
78 87
79 bool hasNotifiers()const; 88 bool hasNotifiers()const;
80 OPimNotifyManager &notifiers()const; 89 OPimNotifyManager &notifiers()const;
81 90
82 ORecur recurrence()const; 91 ORecur recurrence()const;
83 void setRecurrence( const ORecur& ); 92 void setRecurrence( const ORecur& );
84 bool hasRecurrence()const; 93 bool hasRecurrence()const;
85 94
86 QString note()const; 95 QString note()const;
87 void setNote( const QString& note ); 96 void setNote( const QString& note );
88 97
89 98
90 QDateTime createdDateTime()const; 99 QDateTime createdDateTime()const;
91 void setCreatedDateTime( const QDateTime& dt); 100 void setCreatedDateTime( const QDateTime& dt);
92 101
93 /** set the date to dt. dt is the QDateTime in localtime */ 102 /** set the date to dt. dt is the QDateTime in localtime */
94 void setStartDateTime( const QDateTime& ); 103 void setStartDateTime( const QDateTime& );
95 /** returns the datetime in the local timeZone */ 104 /** returns the datetime in the local timeZone */
96 QDateTime startDateTime()const; 105 QDateTime startDateTime()const;
97 106
98 /** returns the start datetime in the current zone */ 107 /** returns the start datetime in the current zone */
99 QDateTime startDateTimeInZone()const; 108 QDateTime startDateTimeInZone()const;
100 109
101 /** in current timezone */ 110 /** in current timezone */
102 void setEndDateTime( const QDateTime& ); 111 void setEndDateTime( const QDateTime& );
103 /** in current timezone */ 112 /** in current timezone */
104 QDateTime endDateTime()const; 113 QDateTime endDateTime()const;
105 QDateTime endDateTimeInZone()const; 114 QDateTime endDateTimeInZone()const;
106 115
107 bool isMultipleDay()const; 116 bool isMultipleDay()const;
108 bool isAllDay()const; 117 bool isAllDay()const;
109 void setAllDay( bool isAllDay ); 118 void setAllDay( bool isAllDay );
110 119
111 /* pin this event to a timezone! FIXME */ 120 /* pin this event to a timezone! FIXME */
112 void setTimeZone( const QString& timeZone ); 121 void setTimeZone( const QString& timeZone );
113 QString timeZone()const; 122 QString timeZone()const;
114 123
115 124
116 virtual bool match( const QRegExp& )const; 125 virtual bool match( const QRegExp& )const;
117 126
118 /** For exception to recurrence here is a list of children... */ 127 /** For exception to recurrence here is a list of children... */
119 QArray<int> children()const; 128 QArray<int> children()const;
120 void setChildren( const QArray<int>& ); 129 void setChildren( const QArray<int>& );
121 void addChild( int uid ); 130 void addChild( int uid );
122 void removeChild( int uid ); 131 void removeChild( int uid );
123 132
124 /** return the parent OEvent */ 133 /** return the parent OEvent */
125 int parent()const; 134 int parent()const;
126 void setParent( int uid ); 135 void setParent( int uid );
127 136
128 137
129 /* needed reimp */ 138 /* needed reimp */
130 QString toRichText()const; 139 QString toRichText()const;
131 QString toShortText()const; 140 QString toShortText()const;
132 QString type()const; 141 QString type()const;
133 142
134 QMap<int, QString> toMap()const; 143 QMap<int, QString> toMap()const;
144 void fromMap( const QMap<int, QString>& map );
135 QString recordField(int )const; 145 QString recordField(int )const;
136 146
137 static int rtti(); 147 static int rtti();
138 148
139 bool loadFromStream( QDataStream& ); 149 bool loadFromStream( QDataStream& );
140 bool saveToStream( QDataStream& )const; 150 bool saveToStream( QDataStream& )const;
141 151
142/* bool operator==( const OEvent& ); 152/* bool operator==( const OEvent& );
143 bool operator!=( const OEvent& ); 153 bool operator!=( const OEvent& );
144 bool operator<( const OEvent& ); 154 bool operator<( const OEvent& );
145 bool operator<=( const OEvent& ); 155 bool operator<=( const OEvent& );
146 bool operator>( const OEvent& ); 156 bool operator>( const OEvent& );
147 bool operator>=(const OEvent& ); 157 bool operator>=(const OEvent& );
148*/ 158*/
149private: 159private:
150 inline void changeOrModify(); 160 inline void changeOrModify();
151 void deref(); 161 void deref();
152 struct Data; 162 struct Data;
153 Data* data; 163 Data* data;
154 class Private; 164 class Private;
155 Private* priv; 165 Private* priv;
156 166
157}; 167};
158 168
159/** 169/**
160 * AN Event can span through multiple days. We split up a multiday eve 170 * AN Event can span through multiple days. We split up a multiday eve
161 */ 171 */
162class OEffectiveEvent { 172class OEffectiveEvent {
163public: 173public:
164 typedef QValueList<OEffectiveEvent> ValueList; 174 typedef QValueList<OEffectiveEvent> ValueList;
165 enum Position { MidWay, Start, End, StartEnd }; 175 enum Position { MidWay, Start, End, StartEnd };
166 // If we calculate the effective event of a multi-day event 176 // If we calculate the effective event of a multi-day event
167 // we have to figure out whether we are at the first day, 177 // we have to figure out whether we are at the first day,
168 // at the end, or anywhere else ("middle"). This is important 178 // at the end, or anywhere else ("middle"). This is important
169 // for the start/end times (00:00/23:59) 179 // for the start/end times (00:00/23:59)
170 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi- 180 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi-
171 // day event 181 // day event
172 // Start: start time -> 23:59 182 // Start: start time -> 23:59
173 // End: 00:00 -> end time 183 // End: 00:00 -> end time
174 // Start | End == StartEnd: for single-day events (default) 184 // Start | End == StartEnd: for single-day events (default)
175 // here we draw start time -> end time 185 // here we draw start time -> end time
176 OEffectiveEvent(); 186 OEffectiveEvent();
177 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd ); 187 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd );
178 OEffectiveEvent( const OEffectiveEvent& ); 188 OEffectiveEvent( const OEffectiveEvent& );
179 OEffectiveEvent &operator=(const OEffectiveEvent& ); 189 OEffectiveEvent &operator=(const OEffectiveEvent& );
180 ~OEffectiveEvent(); 190 ~OEffectiveEvent();
181 191
182 void setStartTime( const QTime& ); 192 void setStartTime( const QTime& );
183 void setEndTime( const QTime& ); 193 void setEndTime( const QTime& );
184 void setEvent( const OEvent& ); 194 void setEvent( const OEvent& );
185 void setDate( const QDate& ); 195 void setDate( const QDate& );
186 196
187 void setEffectiveDates( const QDate& from, const QDate& to ); 197 void setEffectiveDates( const QDate& from, const QDate& to );
188 198
189 QString description()const; 199 QString description()const;
190 QString location()const; 200 QString location()const;
191 QString note()const; 201 QString note()const;
192 OEvent event()const; 202 OEvent event()const;
193 QTime startTime()const; 203 QTime startTime()const;
194 QTime endTime()const; 204 QTime endTime()const;
195 QDate date()const; 205 QDate date()const;
196 206
197 /* return the length in hours */ 207 /* return the length in hours */
198 int length()const; 208 int length()const;
199 int size()const; 209 int size()const;
200 210
201 QDate startDate()const; 211 QDate startDate()const;
202 QDate endDate()const; 212 QDate endDate()const;
203 213
204 bool operator<( const OEffectiveEvent &e ) const; 214 bool operator<( const OEffectiveEvent &e ) const;
205 bool operator<=( const OEffectiveEvent &e ) const; 215 bool operator<=( const OEffectiveEvent &e ) const;
206 bool operator==( const OEffectiveEvent &e ) const; 216 bool operator==( const OEffectiveEvent &e ) const;
207 bool operator!=( const OEffectiveEvent &e ) const; 217 bool operator!=( const OEffectiveEvent &e ) const;
208 bool operator>( const OEffectiveEvent &e ) const; 218 bool operator>( const OEffectiveEvent &e ) const;
209 bool operator>= ( const OEffectiveEvent &e ) const; 219 bool operator>= ( const OEffectiveEvent &e ) const;
210 220
211private: 221private:
212 void deref(); 222 void deref();
213 inline void changeOrModify(); 223 inline void changeOrModify();
214 class Private; 224 class Private;
215 Private* priv; 225 Private* priv;
216 struct Data; 226 struct Data;
217 Data* data; 227 Data* data;
218 228
219}; 229};
220#endif 230#endif