summaryrefslogtreecommitdiff
path: root/libopie2/opiepim
Unidiff
Diffstat (limited to 'libopie2/opiepim') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp11
-rw-r--r--libopie2/opiepim/core/orecur.cpp25
-rw-r--r--libopie2/opiepim/core/orecur.h12
-rw-r--r--libopie2/opiepim/core/otimezone.cpp104
-rw-r--r--libopie2/opiepim/core/otimezone.h71
-rw-r--r--libopie2/opiepim/oevent.cpp427
-rw-r--r--libopie2/opiepim/oevent.h198
-rw-r--r--libopie2/opiepim/otodo.cpp2
8 files changed, 830 insertions, 20 deletions
diff --git a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
index 622d40a..e537269 100644
--- a/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
+++ b/libopie2/opiepim/backend/ocontactaccessbackend_vcard.cpp
@@ -1,173 +1,182 @@
1/* 1/*
2 * VCard Backend for the OPIE-Contact Database. 2 * VCard Backend for the OPIE-Contact Database.
3 * 3 *
4 * Copyright (C) 2000 Trolltech AS. All rights reserved. 4 * Copyright (C) 2000 Trolltech AS. All rights reserved.
5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de) 5 * Copyright (c) 2002 by Stefan Eilers (Eilers.Stefan@epost.de)
6 * 6 *
7 * ===================================================================== 7 * =====================================================================
8 *This program is free software; you can redistribute it and/or 8 *This program is free software; you can redistribute it and/or
9 *modify it under the terms of the GNU Library General Public 9 *modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either 10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version. 11 * version 2 of the License, or (at your option) any later version.
12 * ===================================================================== 12 * =====================================================================
13 * ToDo: 13 * ToDo:
14 * 14 *
15 * ===================================================================== 15 * =====================================================================
16 * Version: $Id$ 16 * Version: $Id$
17 * ===================================================================== 17 * =====================================================================
18 * History: 18 * History:
19 * $Log$ 19 * $Log$
20 * Revision 1.8 2003/02/21 16:52:49 zecke
21 * -Remove old Todo classes they're deprecated and today I already using the
22 * new API
23 * -Guard against self assignment in OTodo
24 * -Add test apps for OPIM
25 * -Opiefied Event classes
26 * -Added TimeZone handling and pinning of TimeZones to OEvent
27 * -Adjust ORecur and the widget to better timezone behaviour
28 *
20 * Revision 1.7 2003/02/16 22:25:46 zecke 29 * Revision 1.7 2003/02/16 22:25:46 zecke
21 * 0000276 Fix for that bug.. or better temp workaround 30 * 0000276 Fix for that bug.. or better temp workaround
22 * A Preferred Number is HOME|VOICE 31 * A Preferred Number is HOME|VOICE
23 * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test 32 * A CellPhone is HOME|VOICE|CELL the type & HOME|VOICE test
24 * triggers both 33 * triggers both
25 * and the cell phone number overrides the other entries.. 34 * and the cell phone number overrides the other entries..
26 * 35 *
27 * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the 36 * as a temp I check that it's not equal to HOME|VOICE|CELL before setting the
28 * number 37 * number
29 * 38 *
30 * The right and final fix would be to reorder the if statement to make it 39 * The right and final fix would be to reorder the if statement to make it
31 * if else based and the less common thing put to the bottom 40 * if else based and the less common thing put to the bottom
32 * 41 *
33 * OTodoAccessVcal fix the date for beaming 42 * OTodoAccessVcal fix the date for beaming
34 * 43 *
35 * Revision 1.6 2003/01/13 15:49:31 eilers 44 * Revision 1.6 2003/01/13 15:49:31 eilers
36 * Fixing crash when businesscard.vcf is missing.. 45 * Fixing crash when businesscard.vcf is missing..
37 * 46 *
38 * Revision 1.5 2002/12/07 13:26:22 eilers 47 * Revision 1.5 2002/12/07 13:26:22 eilers
39 * Fixing bug in storing anniversary.. 48 * Fixing bug in storing anniversary..
40 * 49 *
41 * Revision 1.4 2002/11/13 14:14:51 eilers 50 * Revision 1.4 2002/11/13 14:14:51 eilers
42 * Added sorted for Contacts.. 51 * Added sorted for Contacts..
43 * 52 *
44 * Revision 1.3 2002/11/11 16:41:09 kergoth 53 * Revision 1.3 2002/11/11 16:41:09 kergoth
45 * no default arguments in implementation 54 * no default arguments in implementation
46 * 55 *
47 * Revision 1.2 2002/11/10 15:41:53 eilers 56 * Revision 1.2 2002/11/10 15:41:53 eilers
48 * Bugfixes.. 57 * Bugfixes..
49 * 58 *
50 * Revision 1.1 2002/11/09 14:34:52 eilers 59 * Revision 1.1 2002/11/09 14:34:52 eilers
51 * Added VCard Backend. 60 * Added VCard Backend.
52 * 61 *
53 */ 62 */
54#include "ocontactaccessbackend_vcard.h" 63#include "ocontactaccessbackend_vcard.h"
55#include "../../library/backend/vobject_p.h" 64#include "../../library/backend/vobject_p.h"
56#include "../../library/backend/qfiledirect_p.h" 65#include "../../library/backend/qfiledirect_p.h"
57 66
58#include <qpe/timeconversion.h> 67#include <qpe/timeconversion.h>
59 68
60#include <qfile.h> 69#include <qfile.h>
61 70
62OContactAccessBackend_VCard::OContactAccessBackend_VCard ( QString , QString filename ): 71OContactAccessBackend_VCard::OContactAccessBackend_VCard ( QString , QString filename ):
63 m_dirty( false ), 72 m_dirty( false ),
64 m_file( filename ) 73 m_file( filename )
65{ 74{
66 load(); 75 load();
67} 76}
68 77
69 78
70bool OContactAccessBackend_VCard::load () 79bool OContactAccessBackend_VCard::load ()
71{ 80{
72 m_map.clear(); 81 m_map.clear();
73 m_dirty = false; 82 m_dirty = false;
74 83
75 VObject* obj = 0l; 84 VObject* obj = 0l;
76 85
77 if ( QFile( m_file ).exists() ){ 86 if ( QFile::exists(m_file) ){
78 obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() ); 87 obj = Parse_MIME_FromFileName( QFile::encodeName(m_file).data() );
79 if ( !obj ) 88 if ( !obj )
80 return false; 89 return false;
81 }else{ 90 }else{
82 qWarning("File \"%s\" not found !", m_file.latin1() ); 91 qWarning("File \"%s\" not found !", m_file.latin1() );
83 return false; 92 return false;
84 } 93 }
85 94
86 while ( obj ) { 95 while ( obj ) {
87 OContact con = parseVObject( obj ); 96 OContact con = parseVObject( obj );
88 /* 97 /*
89 * if uid is 0 assign a new one 98 * if uid is 0 assign a new one
90 * this at least happens on 99 * this at least happens on
91 * Nokia6210 100 * Nokia6210
92 */ 101 */
93 if ( con.uid() == 0 ){ 102 if ( con.uid() == 0 ){
94 con.setUid( 1 ); 103 con.setUid( 1 );
95 qWarning("assigned new uid %d",con.uid() ); 104 qWarning("assigned new uid %d",con.uid() );
96 } 105 }
97 106
98 m_map.insert( con.uid(), con ); 107 m_map.insert( con.uid(), con );
99 108
100 VObject *t = obj; 109 VObject *t = obj;
101 obj = nextVObjectInList(obj); 110 obj = nextVObjectInList(obj);
102 cleanVObject( t ); 111 cleanVObject( t );
103 } 112 }
104 113
105 return true; 114 return true;
106 115
107} 116}
108bool OContactAccessBackend_VCard::reload() 117bool OContactAccessBackend_VCard::reload()
109{ 118{
110 return load(); 119 return load();
111} 120}
112bool OContactAccessBackend_VCard::save() 121bool OContactAccessBackend_VCard::save()
113{ 122{
114 if (!m_dirty ) 123 if (!m_dirty )
115 return true; 124 return true;
116 125
117 QFileDirect file( m_file ); 126 QFileDirect file( m_file );
118 if (!file.open(IO_WriteOnly ) ) 127 if (!file.open(IO_WriteOnly ) )
119 return false; 128 return false;
120 129
121 VObject *obj; 130 VObject *obj;
122 obj = newVObject( VCCalProp ); 131 obj = newVObject( VCCalProp );
123 addPropValue( obj, VCVersionProp, "1.0" ); 132 addPropValue( obj, VCVersionProp, "1.0" );
124 133
125 VObject *vo; 134 VObject *vo;
126 for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){ 135 for(QMap<int, OContact>::ConstIterator it=m_map.begin(); it !=m_map.end(); ++it ){
127 vo = createVObject( *it ); 136 vo = createVObject( *it );
128 writeVObject( file.directHandle() , vo ); 137 writeVObject( file.directHandle() , vo );
129 cleanVObject( vo ); 138 cleanVObject( vo );
130 } 139 }
131 cleanStrTbl(); 140 cleanStrTbl();
132 141
133 m_dirty = false; 142 m_dirty = false;
134 return true; 143 return true;
135 144
136 145
137} 146}
138void OContactAccessBackend_VCard::clear () 147void OContactAccessBackend_VCard::clear ()
139{ 148{
140 m_map.clear(); 149 m_map.clear();
141 m_dirty = true; // ??? sure ? (se) 150 m_dirty = true; // ??? sure ? (se)
142} 151}
143 152
144bool OContactAccessBackend_VCard::add ( const OContact& newcontact ) 153bool OContactAccessBackend_VCard::add ( const OContact& newcontact )
145{ 154{
146 m_map.insert( newcontact.uid(), newcontact ); 155 m_map.insert( newcontact.uid(), newcontact );
147 m_dirty = true; 156 m_dirty = true;
148 return true; 157 return true;
149} 158}
150 159
151bool OContactAccessBackend_VCard::remove ( int uid ) 160bool OContactAccessBackend_VCard::remove ( int uid )
152{ 161{
153 m_map.remove( uid ); 162 m_map.remove( uid );
154 m_dirty = true; 163 m_dirty = true;
155 return true; 164 return true;
156} 165}
157 166
158bool OContactAccessBackend_VCard::replace ( const OContact &contact ) 167bool OContactAccessBackend_VCard::replace ( const OContact &contact )
159{ 168{
160 m_map.replace( contact.uid(), contact ); 169 m_map.replace( contact.uid(), contact );
161 m_dirty = true; 170 m_dirty = true;
162 return true; 171 return true;
163} 172}
164 173
165OContact OContactAccessBackend_VCard::find ( int uid ) const 174OContact OContactAccessBackend_VCard::find ( int uid ) const
166{ 175{
167 return m_map[uid]; 176 return m_map[uid];
168} 177}
169 178
170QArray<int> OContactAccessBackend_VCard::allRecords() const 179QArray<int> OContactAccessBackend_VCard::allRecords() const
171{ 180{
172 QArray<int> ar( m_map.count() ); 181 QArray<int> ar( m_map.count() );
173 QMap<int, OContact>::ConstIterator it; 182 QMap<int, OContact>::ConstIterator it;
diff --git a/libopie2/opiepim/core/orecur.cpp b/libopie2/opiepim/core/orecur.cpp
index daf3506..e6a4787 100644
--- a/libopie2/opiepim/core/orecur.cpp
+++ b/libopie2/opiepim/core/orecur.cpp
@@ -1,150 +1,152 @@
1#include <qshared.h> 1#include <qshared.h>
2 2
3#include <qtopia/timeconversion.h> 3#include <qtopia/timeconversion.h>
4 4
5#include "orecur.h" 5#include "orecur.h"
6 6
7struct ORecur::Data : public QShared { 7struct ORecur::Data : public QShared {
8 Data() : QShared() { 8 Data() : QShared() {
9 type = ORecur::NoRepeat; 9 type = ORecur::NoRepeat;
10 freq = -1; 10 freq = -1;
11 days = 0; 11 days = 0;
12 pos = 0; 12 pos = 0;
13 create = -1; 13 create = QDateTime::currentDateTime();
14 hasEnd = FALSE; 14 hasEnd = FALSE;
15 end = 0; 15 end = QDate::currentDate();
16 } 16 }
17 char days; // Q_UINT8 for 8 seven days;) 17 char days; // Q_UINT8 for 8 seven days;)
18 ORecur::RepeatType type; 18 ORecur::RepeatType type;
19 int freq; 19 int freq;
20 int pos; 20 int pos;
21 bool hasEnd : 1; 21 bool hasEnd : 1;
22 time_t end; 22 QDate end;
23 time_t create; 23 QDateTime create;
24 int rep; 24 int rep;
25 QString app; 25 QString app;
26 ExceptionList list; 26 ExceptionList list;
27 QDate start; 27 QDate start;
28}; 28};
29 29
30 30
31ORecur::ORecur() { 31ORecur::ORecur() {
32 data = new Data; 32 data = new Data;
33} 33}
34ORecur::ORecur( const ORecur& rec) 34ORecur::ORecur( const ORecur& rec)
35 : data( rec.data ) 35 : data( rec.data )
36{ 36{
37 data->ref(); 37 data->ref();
38} 38}
39ORecur::~ORecur() { 39ORecur::~ORecur() {
40 if ( data->deref() ) { 40 if ( data->deref() ) {
41 delete data; 41 delete data;
42 data = 0l; 42 data = 0l;
43 } 43 }
44} 44}
45void ORecur::deref() { 45void ORecur::deref() {
46 if ( data->deref() ) { 46 if ( data->deref() ) {
47 delete data; 47 delete data;
48 data = 0l; 48 data = 0l;
49 } 49 }
50} 50}
51bool ORecur::operator==( const ORecur& )const { 51bool ORecur::operator==( const ORecur& )const {
52 return false; 52 return false;
53} 53}
54ORecur &ORecur::operator=( const ORecur& re) { 54ORecur &ORecur::operator=( const ORecur& re) {
55 if ( *this == re ) return *this;
56
55 re.data->ref(); 57 re.data->ref();
56 deref(); 58 deref();
57 data = re.data; 59 data = re.data;
58 60
59 return *this; 61 return *this;
60} 62}
61bool ORecur::doesRecur()const { 63bool ORecur::doesRecur()const {
62 return !( type() == NoRepeat ); 64 return !( type() == NoRepeat );
63} 65}
64/* 66/*
65 * we try to be smart here 67 * we try to be smart here
66 * 68 *
67 */ 69 */
68bool ORecur::doesRecur( const QDate& date ) { 70bool ORecur::doesRecur( const QDate& date ) {
69 /* the day before the recurrance */ 71 /* the day before the recurrance */
70 QDate da = date.addDays(-1); 72 QDate da = date.addDays(-1);
71 73
72 QDate recur; 74 QDate recur;
73 if (!nextOcurrence( da, recur ) ) 75 if (!nextOcurrence( da, recur ) )
74 return false; 76 return false;
75 77
76 return (recur == date); 78 return (recur == date);
77} 79}
78// FIXME unuglify! 80// FIXME unuglify!
79// GPL from Datebookdb.cpp 81// GPL from Datebookdb.cpp
80// FIXME exception list! 82// FIXME exception list!
81bool ORecur::nextOcurrence( const QDate& from, QDate& next ) { 83bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
82 84
83 // easy checks, first are we too far in the future or too far in the past? 85 // easy checks, first are we too far in the future or too far in the past?
84 QDate tmpDate; 86 QDate tmpDate;
85 int freq = frequency(); 87 int freq = frequency();
86 int diff, diff2, a; 88 int diff, diff2, a;
87 int iday, imonth, iyear; 89 int iday, imonth, iyear;
88 int dayOfWeek = 0; 90 int dayOfWeek = 0;
89 int firstOfWeek = 0; 91 int firstOfWeek = 0;
90 int weekOfMonth; 92 int weekOfMonth;
91 93
92 94
93 if (hasEndDate() && endDate() < from) 95 if (hasEndDate() && endDate() < from)
94 return FALSE; 96 return FALSE;
95 97
96 if (start() >= from) { 98 if (start() >= from) {
97 next = start(); 99 next = start();
98 return TRUE; 100 return TRUE;
99 } 101 }
100 102
101 switch ( type() ) { 103 switch ( type() ) {
102 case Weekly: 104 case Weekly:
103 /* weekly is just daily by 7 */ 105 /* weekly is just daily by 7 */
104 /* first convert the repeatPattern.Days() mask to the next 106 /* first convert the repeatPattern.Days() mask to the next
105 day of week valid after from */ 107 day of week valid after from */
106 dayOfWeek = from.dayOfWeek(); 108 dayOfWeek = from.dayOfWeek();
107 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */ 109 dayOfWeek--; /* we want 0-6, doco for above specs 1-7 */
108 110
109 /* this is done in case freq > 1 and from in week not 111 /* this is done in case freq > 1 and from in week not
110 for this round */ 112 for this round */
111 // firstOfWeek = 0; this is already done at decl. 113 // firstOfWeek = 0; this is already done at decl.
112 while(!((1 << firstOfWeek) & days() )) 114 while(!((1 << firstOfWeek) & days() ))
113 firstOfWeek++; 115 firstOfWeek++;
114 116
115 /* there is at least one 'day', or there would be no event */ 117 /* there is at least one 'day', or there would be no event */
116 while(!((1 << (dayOfWeek % 7)) & days() )) 118 while(!((1 << (dayOfWeek % 7)) & days() ))
117 dayOfWeek++; 119 dayOfWeek++;
118 120
119 dayOfWeek = dayOfWeek % 7; /* the actual day of week */ 121 dayOfWeek = dayOfWeek % 7; /* the actual day of week */
120 dayOfWeek -= start().dayOfWeek() -1; 122 dayOfWeek -= start().dayOfWeek() -1;
121 123
122 firstOfWeek = firstOfWeek % 7; /* the actual first of week */ 124 firstOfWeek = firstOfWeek % 7; /* the actual first of week */
123 firstOfWeek -= start().dayOfWeek() -1; 125 firstOfWeek -= start().dayOfWeek() -1;
124 126
125 // dayOfWeek may be negitive now 127 // dayOfWeek may be negitive now
126 // day of week is number of days to add to start day 128 // day of week is number of days to add to start day
127 129
128 freq *= 7; 130 freq *= 7;
129 // FALL-THROUGH !!!!! 131 // FALL-THROUGH !!!!!
130 case Daily: 132 case Daily:
131 // the add is for the possible fall through from weekly */ 133 // the add is for the possible fall through from weekly */
132 if(start().addDays(dayOfWeek) > from) { 134 if(start().addDays(dayOfWeek) > from) {
133 /* first week exception */ 135 /* first week exception */
134 next = QDate(start().addDays(dayOfWeek) ); 136 next = QDate(start().addDays(dayOfWeek) );
135 if ((next > endDate()) 137 if ((next > endDate())
136 && hasEndDate() ) 138 && hasEndDate() )
137 return FALSE; 139 return FALSE;
138 return TRUE; 140 return TRUE;
139 } 141 }
140 /* if from is middle of a non-week */ 142 /* if from is middle of a non-week */
141 143
142 diff = start().addDays(dayOfWeek).daysTo(from) % freq; 144 diff = start().addDays(dayOfWeek).daysTo(from) % freq;
143 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq; 145 diff2 = start().addDays(firstOfWeek).daysTo(from) % freq;
144 146
145 if(diff != 0) 147 if(diff != 0)
146 diff = freq - diff; 148 diff = freq - diff;
147 if(diff2 != 0) 149 if(diff2 != 0)
148 diff2 = freq - diff2; 150 diff2 = freq - diff2;
149 diff = QMIN(diff, diff2); 151 diff = QMIN(diff, diff2);
150 152
@@ -273,179 +275,172 @@ bool ORecur::nextOcurrence( const QDate& from, QDate& next ) {
273 /* done */ 275 /* done */
274 next = QDate(iyear, imonth, iday); 276 next = QDate(iyear, imonth, iday);
275 if ((next > endDate()) && hasEndDate() ) 277 if ((next > endDate()) && hasEndDate() )
276 return FALSE; 278 return FALSE;
277 return TRUE; 279 return TRUE;
278 } 280 }
279 281
280 /* ok, need to cycle */ 282 /* ok, need to cycle */
281 imonth += freq; 283 imonth += freq;
282 imonth--; 284 imonth--;
283 iyear += imonth / 12; 285 iyear += imonth / 12;
284 imonth = imonth % 12; 286 imonth = imonth % 12;
285 imonth++; 287 imonth++;
286 288
287 while(!QDate::isValid(iyear, imonth, iday) ) { 289 while(!QDate::isValid(iyear, imonth, iday) ) {
288 imonth += freq; 290 imonth += freq;
289 imonth--; 291 imonth--;
290 iyear += imonth / 12; 292 iyear += imonth / 12;
291 imonth = imonth % 12; 293 imonth = imonth % 12;
292 imonth++; 294 imonth++;
293 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() ) 295 if ((QDate(iyear, imonth, 1) > endDate()) && hasEndDate() )
294 return FALSE; 296 return FALSE;
295 } 297 }
296 298
297 next = QDate(iyear, imonth, iday); 299 next = QDate(iyear, imonth, iday);
298 if ((next > endDate()) && hasEndDate() ) 300 if ((next > endDate()) && hasEndDate() )
299 return FALSE; 301 return FALSE;
300 return TRUE; 302 return TRUE;
301 case Yearly: 303 case Yearly:
302 iday = start().day(); 304 iday = start().day();
303 imonth = start().month(); 305 imonth = start().month();
304 iyear = from.year(); // after all, we want to start in this year 306 iyear = from.year(); // after all, we want to start in this year
305 307
306 diff = 1; 308 diff = 1;
307 if(imonth == 2 && iday > 28) { 309 if(imonth == 2 && iday > 28) {
308 /* leap year, and it counts, calculate actual frequency */ 310 /* leap year, and it counts, calculate actual frequency */
309 if(freq % 4) 311 if(freq % 4)
310 if (freq % 2) 312 if (freq % 2)
311 freq = freq * 4; 313 freq = freq * 4;
312 else 314 else
313 freq = freq * 2; 315 freq = freq * 2;
314 /* else divides by 4 already, leave freq alone */ 316 /* else divides by 4 already, leave freq alone */
315 diff = 4; 317 diff = 4;
316 } 318 }
317 319
318 a = from.year() - start().year(); 320 a = from.year() - start().year();
319 if(a % freq) { 321 if(a % freq) {
320 a = freq - (a % freq); 322 a = freq - (a % freq);
321 iyear = iyear + a; 323 iyear = iyear + a;
322 } 324 }
323 325
324 /* under the assumption we won't hit one of the special not-leap years twice */ 326 /* under the assumption we won't hit one of the special not-leap years twice */
325 if(!QDate::isValid(iyear, imonth, iday)) { 327 if(!QDate::isValid(iyear, imonth, iday)) {
326 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ 328 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
327 iyear += freq; 329 iyear += freq;
328 } 330 }
329 331
330 if(QDate(iyear, imonth, iday) >= from) { 332 if(QDate(iyear, imonth, iday) >= from) {
331 next = QDate(iyear, imonth, iday); 333 next = QDate(iyear, imonth, iday);
332 334
333 if ((next > endDate()) && hasEndDate() ) 335 if ((next > endDate()) && hasEndDate() )
334 return FALSE; 336 return FALSE;
335 return TRUE; 337 return TRUE;
336 } 338 }
337 /* iyear == from.year(), need to advance again */ 339 /* iyear == from.year(), need to advance again */
338 iyear += freq; 340 iyear += freq;
339 /* under the assumption we won't hit one of the special not-leap years twice */ 341 /* under the assumption we won't hit one of the special not-leap years twice */
340 if(!QDate::isValid(iyear, imonth, iday)) { 342 if(!QDate::isValid(iyear, imonth, iday)) {
341 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */ 343 /* must have been skipping by leap years and hit one that wasn't, (e.g. 2100) */
342 iyear += freq; 344 iyear += freq;
343 } 345 }
344 346
345 next = QDate(iyear, imonth, iday); 347 next = QDate(iyear, imonth, iday);
346 if ((next > endDate()) && hasEndDate() ) 348 if ((next > endDate()) && hasEndDate() )
347 return FALSE; 349 return FALSE;
348 return TRUE; 350 return TRUE;
349 default: 351 default:
350 return FALSE; 352 return FALSE;
351 } 353 }
352} 354}
353ORecur::RepeatType ORecur::type()const{ 355ORecur::RepeatType ORecur::type()const{
354 return data->type; 356 return data->type;
355} 357}
356int ORecur::frequency()const { 358int ORecur::frequency()const {
357 return data->freq; 359 return data->freq;
358} 360}
359int ORecur::position()const { 361int ORecur::position()const {
360 return data->pos; 362 return data->pos;
361} 363}
362char ORecur::days() const{ 364char ORecur::days() const{
363 return data->days; 365 return data->days;
364} 366}
365bool ORecur::hasEndDate()const { 367bool ORecur::hasEndDate()const {
366 return data->hasEnd; 368 return data->hasEnd;
367} 369}
368QDate ORecur::endDate()const { 370QDate ORecur::endDate()const {
369 return TimeConversion::fromUTC( data->end ).date(); 371 return data->end;
370} 372}
371QDate ORecur::start()const{ 373QDate ORecur::start()const{
372 return data->start; 374 return data->start;
373} 375}
374time_t ORecur::endDateUTC()const { 376QDateTime ORecur::createdDateTime()const {
375 return data->end;
376}
377time_t ORecur::createTime()const {
378 return data->create; 377 return data->create;
379} 378}
380int ORecur::repetition()const { 379int ORecur::repetition()const {
381 return data->rep; 380 return data->rep;
382} 381}
383QString ORecur::service()const { 382QString ORecur::service()const {
384 return data->app; 383 return data->app;
385} 384}
386ORecur::ExceptionList& ORecur::exceptions() { 385ORecur::ExceptionList& ORecur::exceptions() {
387 return data->list; 386 return data->list;
388} 387}
389void ORecur::setType( const RepeatType& z) { 388void ORecur::setType( const RepeatType& z) {
390 checkOrModify(); 389 checkOrModify();
391 data->type = z; 390 data->type = z;
392} 391}
393void ORecur::setFrequency( int freq ) { 392void ORecur::setFrequency( int freq ) {
394 checkOrModify(); 393 checkOrModify();
395 data->freq = freq; 394 data->freq = freq;
396} 395}
397void ORecur::setPosition( int pos ) { 396void ORecur::setPosition( int pos ) {
398 checkOrModify(); 397 checkOrModify();
399 data->pos = pos; 398 data->pos = pos;
400} 399}
401void ORecur::setDays( char c ) { 400void ORecur::setDays( char c ) {
402 checkOrModify(); 401 checkOrModify();
403 data->days = c; 402 data->days = c;
404} 403}
405void ORecur::setEndDate( const QDate& dt) { 404void ORecur::setEndDate( const QDate& dt) {
406 checkOrModify(); 405 checkOrModify();
407 data->end = TimeConversion::toUTC( dt ); 406 data->end = dt;
408}
409void ORecur::setEndDateUTC( time_t t) {
410 checkOrModify();
411 data->end = t;
412} 407}
413void ORecur::setCreateTime( time_t t) { 408void ORecur::setCreatedDateTime( const QDateTime& t) {
414 checkOrModify(); 409 checkOrModify();
415 data->create = t; 410 data->create = t;
416} 411}
417void ORecur::setHasEndDate( bool b) { 412void ORecur::setHasEndDate( bool b) {
418 checkOrModify(); 413 checkOrModify();
419 data->hasEnd = b; 414 data->hasEnd = b;
420} 415}
421void ORecur::setRepitition( int rep ) { 416void ORecur::setRepitition( int rep ) {
422 checkOrModify(); 417 checkOrModify();
423 data->rep = rep; 418 data->rep = rep;
424} 419}
425void ORecur::setService( const QString& app ) { 420void ORecur::setService( const QString& app ) {
426 checkOrModify(); 421 checkOrModify();
427 data->app = app; 422 data->app = app;
428} 423}
429void ORecur::setStart( const QDate& dt ) { 424void ORecur::setStart( const QDate& dt ) {
430 checkOrModify(); 425 checkOrModify();
431 data->start = dt; 426 data->start = dt;
432} 427}
433void ORecur::checkOrModify() { 428void ORecur::checkOrModify() {
434 if ( data->count != 1 ) { 429 if ( data->count != 1 ) {
435 data->deref(); 430 data->deref();
436 Data* d2 = new Data; 431 Data* d2 = new Data;
437 d2->days = data->days; 432 d2->days = data->days;
438 d2->type = data->type; 433 d2->type = data->type;
439 d2->freq = data->freq; 434 d2->freq = data->freq;
440 d2->pos = data->pos; 435 d2->pos = data->pos;
441 d2->hasEnd = data->hasEnd; 436 d2->hasEnd = data->hasEnd;
442 d2->end = data->end; 437 d2->end = data->end;
443 d2->create = data->create; 438 d2->create = data->create;
444 d2->rep = data->rep; 439 d2->rep = data->rep;
445 d2->app = data->app; 440 d2->app = data->app;
446 d2->list = data->list; 441 d2->list = data->list;
447 d2->start = data->start; 442 d2->start = data->start;
448 data = d2; 443 data = d2;
449 } 444 }
450} 445}
451 446
diff --git a/libopie2/opiepim/core/orecur.h b/libopie2/opiepim/core/orecur.h
index 8713d97..1e0014b 100644
--- a/libopie2/opiepim/core/orecur.h
+++ b/libopie2/opiepim/core/orecur.h
@@ -1,83 +1,87 @@
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 12
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 ORecur(); 21 ORecur();
22 ORecur( const ORecur& ); 22 ORecur( const ORecur& );
23 ~ORecur(); 23 ~ORecur();
24 24
25 ORecur &operator=( const ORecur& ); 25 ORecur &operator=( const ORecur& );
26 bool operator==(const ORecur& )const; 26 bool operator==(const ORecur& )const;
27 27
28 bool doesRecur()const; 28 bool doesRecur()const;
29 /* if it recurrs on that day */ 29 /* if it recurrs on that day */
30 bool doesRecur( const QDate& ); 30 bool doesRecur( const QDate& );
31 RepeatType type()const; 31 RepeatType type()const;
32 int frequency()const; 32 int frequency()const;
33 int position()const; 33 int position()const;
34 char days()const; 34 char days()const;
35 bool hasEndDate()const; 35 bool hasEndDate()const;
36 QDate start()const; 36 QDate start()const;
37 QDate endDate()const; 37 QDate endDate()const;
38 time_t endDateUTC()const; 38 QDateTime createdDateTime()const;
39 time_t createTime()const; 39 /**
40 * starting on monday=0, sunday=6
41 * for convience
42 */
43 bool repeatOnWeekDay( int day )const;
40 44
41 /** 45 /**
42 * FromWhereToStart is not included!!! 46 * FromWhereToStart is not included!!!
43 */ 47 */
44 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate ); 48 bool nextOcurrence( const QDate& FromWhereToStart, QDate &recurDate );
49
45 /** 50 /**
46 * The module this ORecur belongs to 51 * The module this ORecur belongs to
47 */ 52 */
48 QString service()const; 53 QString service()const;
49 54
50 /* 55 /*
51 * reference to the exception list 56 * reference to the exception list
52 */ 57 */
53 ExceptionList &exceptions(); 58 ExceptionList &exceptions();
54 59
55 /** 60 /**
56 * the current repetition 61 * the current repetition
57 */ 62 */
58 int repetition()const; 63 int repetition()const;
59 64
60 void setType( const RepeatType& ); 65 void setType( const RepeatType& );
61 void setFrequency( int freq ); 66 void setFrequency( int freq );
62 void setPosition( int pos ); 67 void setPosition( int pos );
63 void setDays( char c); 68 void setDays( char c);
64 void setEndDate( const QDate& dt ); 69 void setEndDate( const QDate& dt );
65 void setStart( const QDate& dt ); 70 void setStart( const QDate& dt );
66 void setEndDateUTC( time_t ); 71 void setCreatedDateTime( const QDateTime& );
67 void setCreateTime( time_t );
68 void setHasEndDate( bool b ); 72 void setHasEndDate( bool b );
69 void setRepitition(int ); 73 void setRepitition(int );
70 74
71 void setService( const QString& ser ); 75 void setService( const QString& ser );
72private: 76private:
73 void deref(); 77 void deref();
74 inline void checkOrModify(); 78 inline void checkOrModify();
75 79
76 80
77 class Data; 81 class Data;
78 Data* data; 82 Data* data;
79 class ORecurPrivate; 83 class ORecurPrivate;
80 ORecurPrivate *d; 84 ORecurPrivate *d;
81}; 85};
82 86
83#endif 87#endif
diff --git a/libopie2/opiepim/core/otimezone.cpp b/libopie2/opiepim/core/otimezone.cpp
new file mode 100644
index 0000000..b2bd3aa
--- a/dev/null
+++ b/libopie2/opiepim/core/otimezone.cpp
@@ -0,0 +1,104 @@
1#include <stdio.h>
2#include <stdlib.h>
3
4#include <sys/types.h>
5
6#include "otimezone.h"
7
8namespace {
9
10 QDateTime utcTime( time_t t) {
11 tm* broken = ::gmtime( &t );
12 QDateTime ret;
13 ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) );
14 ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) );
15 return ret;
16 }
17 QDateTime utcTime( time_t t, const QString& zone) {
18 QCString org = ::getenv( "TZ" );
19 ::setenv( "TZ", zone.latin1(), true );
20 ::tzset();
21
22 tm* broken = ::localtime( &t );
23 ::setenv( "TZ", org, true );
24
25 QDateTime ret;
26 ret.setDate( QDate( broken->tm_year + 1900, broken->tm_mon +1, broken->tm_mday ) );
27 ret.setTime( QTime( broken->tm_hour, broken->tm_min, broken->tm_sec ) );
28
29 return ret;
30 }
31 time_t to_Time_t( const QDateTime& utc, const QString& str ) {
32 QDate d = utc.date();
33 QTime t = utc.time();
34
35 tm broken;
36 broken.tm_year = d.year() - 1900;
37 broken.tm_mon = d.month() - 1;
38 broken.tm_mday = d.day();
39 broken.tm_hour = t.hour();
40 broken.tm_min = t.minute();
41 broken.tm_sec = t.second();
42
43 QCString org = ::getenv( "TZ" );
44 ::setenv( "TZ", str.latin1(), true );
45 ::tzset();
46
47 time_t ti = ::mktime( &broken );
48 ::setenv( "TZ", org, true );
49
50 return ti;
51 }
52}
53OTimeZone::OTimeZone( const ZoneName& zone )
54 : m_name(zone) {
55}
56OTimeZone::~OTimeZone() {
57}
58
59bool OTimeZone::isValid()const {
60 return !m_name.isEmpty();
61}
62
63/*
64 * we will get the current timezone
65 * and ask it to convert to the timezone date
66 */
67QDateTime OTimeZone::toLocalDateTime( const QDateTime& dt) {
68 return OTimeZone::current().toDateTime( dt, *this );
69}
70QDateTime OTimeZone::toUTCDateTime( const QDateTime& dt ) {
71 return OTimeZone::utc().toDateTime( dt, *this );
72}
73QDateTime OTimeZone::fromUTCDateTime( time_t t) {
74 return utcTime( t );
75}
76QDateTime OTimeZone::toDateTime( time_t t) {
77 return utcTime( t, m_name );
78}
79/*
80 * convert dt to utc using zone.m_name
81 * convert utc -> timeZoneDT using this->m_name
82 */
83QDateTime OTimeZone::toDateTime( const QDateTime& dt, const OTimeZone& zone ) {
84 time_t utc = to_Time_t( dt, zone.m_name );
85 qWarning("%d %s", utc, zone.m_name.latin1() );
86 return utcTime( utc, m_name );
87}
88time_t OTimeZone::fromDateTime( const QDateTime& time ) {
89 return to_Time_t( time, m_name );
90}
91time_t OTimeZone::fromUTCDateTime( const QDateTime& time ) {
92 return to_Time_t( time, "UTC" );
93}
94OTimeZone OTimeZone::current() {
95 QCString str = ::getenv("TZ");
96 OTimeZone zone( str );
97 return zone;
98}
99OTimeZone OTimeZone::utc() {
100 return OTimeZone("UTC");
101}
102QString OTimeZone::timeZone()const {
103 return m_name;
104}
diff --git a/libopie2/opiepim/core/otimezone.h b/libopie2/opiepim/core/otimezone.h
new file mode 100644
index 0000000..bb08349
--- a/dev/null
+++ b/libopie2/opiepim/core/otimezone.h
@@ -0,0 +1,71 @@
1#ifndef OPIE_TIME_ZONE_H
2#define OPIE_TIME_ZONE_H
3
4#include <time.h>
5#include <qdatetime.h>
6
7/**
8 * A very primitive class to convert time
9 * from one timezone to another
10 * and to localtime
11 * and time_t
12 */
13class OTimeZone {
14 public:
15 typedef QString ZoneName;
16 OTimeZone( const ZoneName& = ZoneName::null );
17 virtual ~OTimeZone(); // just in case.
18
19 bool isValid()const;
20
21 /**
22 * converts the QDateTime to a DateTime
23 * in the local timezone
24 * if QDateTime is 25th Jan and takes place in Europe/Berlin at 12h
25 * and the current timezone is Europe/London the returned
26 * time will be 11h.
27 */
28 QDateTime toLocalDateTime( const QDateTime& dt );
29
30 /**
31 * converts the QDateTime to UTC time
32 */
33 QDateTime toUTCDateTime( const QDateTime& dt );
34
35 /**
36 * reads the time_t into a QDateTime using UTC as timezone!
37 */
38 QDateTime fromUTCDateTime( time_t );
39
40 /**
41 * converts the time_t to the time in the timezone
42 */
43 QDateTime toDateTime( time_t );
44
45 /**
46 * converts the QDateTime from one timezone to this timeZone
47 */
48 QDateTime toDateTime( const QDateTime&, const OTimeZone& timeZone );
49
50 /**
51 * converts the date time into a time_t. It takes the timezone into account
52 */
53 time_t fromDateTime( const QDateTime& );
54
55 /**
56 * converts the datetime with timezone UTC
57 */
58 time_t fromUTCDateTime( const QDateTime& );
59
60 static OTimeZone current();
61 static OTimeZone utc();
62
63 QString timeZone()const;
64 private:
65 ZoneName m_name;
66 class Private;
67 Private* d;
68};
69
70
71#endif
diff --git a/libopie2/opiepim/oevent.cpp b/libopie2/opiepim/oevent.cpp
new file mode 100644
index 0000000..71b9441
--- a/dev/null
+++ b/libopie2/opiepim/oevent.cpp
@@ -0,0 +1,427 @@
1#include <qshared.h>
2
3#include <qpe/palmtopuidgen.h>
4#include <qpe/categories.h>
5
6#include "orecur.h"
7#include "opimresolver.h"
8#include "opimnotifymanager.h"
9
10#include "oevent.h"
11
12namespace OCalendarHelper {
13 static int week( const QDate& date) {
14 // Calculates the week this date is in within that
15 // month. Equals the "row" is is in in the month view
16 int week = 1;
17 QDate tmp( date.year(), date.month(), 1 );
18 if ( date.dayOfWeek() < tmp.dayOfWeek() )
19 ++week;
20
21 week += ( date.day() - 1 ) / 7;
22
23 return week;
24 }
25 static int occurence( const QDate& date) {
26 // calculates the number of occurrances of this day of the
27 // week till the given date (e.g 3rd Wednesday of the month)
28 return ( date.day() - 1 ) / 7 + 1;
29 }
30 static int dayOfWeek( char day ) {
31 int dayOfWeek = 1;
32 char i = ORecur::MON;
33 while ( !( i & day ) && i <= ORecur::SUN ) {
34 i <<= 1;
35 ++dayOfWeek;
36 }
37 return dayOfWeek;
38 }
39 static int monthDiff( const QDate& first, const QDate& second ) {
40 return ( second.year() - first.year() ) * 12 +
41 second.month() - first.month();
42 }
43}
44
45struct OEvent::Data : public QShared {
46 Data() : QShared() {
47 recur = 0;
48 manager = 0;
49 isAllDay = false;
50 }
51 ~Data() {
52 delete manager;
53 delete recur;
54 }
55 QString description;
56 QString location;
57 OPimNotifyManager* manager;
58 ORecur* recur;
59 QString note;
60 QDateTime created;
61 QDateTime start;
62 QDateTime end;
63 bool isAllDay : 1;
64 QString timezone;
65};
66
67OEvent::OEvent( int uid )
68 : OPimRecord( uid ) {
69 data = new Data;
70}
71OEvent::OEvent( const OEvent& ev)
72 : OPimRecord( ev ), data( ev.data )
73{
74 data->ref();
75}
76OEvent::~OEvent() {
77 if ( data->deref() ) {
78 delete data;
79 data = 0;
80 }
81}
82OEvent& OEvent::operator=( const OEvent& ev) {
83 if ( *this == ev ) return *this;
84
85 OPimRecord::operator=( ev );
86 ev.data->ref();
87 deref();
88 data = ev.data;
89
90
91 return *this;
92}
93QString OEvent::description()const {
94 return data->description;
95}
96void OEvent::setDescription( const QString& description ) {
97 changeOrModify();
98 data->description = description;
99}
100void OEvent::setLocation( const QString& loc ) {
101 changeOrModify();
102 data->location = loc;
103}
104QString OEvent::location()const {
105 return data->location;
106}
107OPimNotifyManager &OEvent::notifiers() {
108 // I hope we can skip the changeOrModify here
109 // the notifier should take care of it
110 // and OPimNotify is shared too
111 if (!data->manager )
112 data->manager = new OPimNotifyManager;
113
114 return *data->manager;
115}
116bool OEvent::hasNotifiers()const {
117 return ( data->manager);
118}
119ORecur OEvent::recurrence()const {
120 if (!data->recur)
121 data->recur = new ORecur;
122
123 return *data->recur;
124}
125void OEvent::setRecurrence( const ORecur& rec) {
126 changeOrModify();
127 if (data->recur )
128 (*data->recur) = rec;
129 else
130 data->recur = new ORecur( rec );
131}
132bool OEvent::hasRecurrence()const {
133 return data->recur;
134}
135QString OEvent::note()const {
136 return data->note;
137}
138void OEvent::setNote( const QString& note ) {
139 changeOrModify();
140 data->note = note;
141}
142QDateTime OEvent::createdDateTime()const {
143 return data->created;
144}
145void OEvent::setCreatedDateTime( const QDateTime& time ) {
146 changeOrModify();
147 data->created = time;
148}
149QDateTime OEvent::startDateTime()const {
150 if ( data->isAllDay )
151 return QDateTime( data->start.date(), QTime(0, 0, 0 ) );
152 return data->start;
153}
154QDateTime OEvent::startDateTimeInZone()const {
155 /* if no timezone, or all day event or if the current and this timeZone match... */
156 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return startDateTime();
157
158 OTimeZone zone(data->timezone );
159 return zone.toDateTime( data->start, OTimeZone::current() );
160}
161void OEvent::setStartDateTime( const QDateTime& dt ) {
162 changeOrModify();
163 data->start = dt;
164}
165QDateTime OEvent::endDateTime()const {
166 /*
167 * if all Day event the end time needs
168 * to be on the same day as the start
169 */
170 if ( data->isAllDay )
171 return QDateTime( data->start.date(), QTime(23, 59, 59 ) );
172 return data->end;
173}
174QDateTime OEvent::endDateTimeInZone()const {
175 /* if no timezone, or all day event or if the current and this timeZone match... */
176 if (data->timezone.isEmpty() || data->isAllDay || data->timezone == OTimeZone::current().timeZone() ) return endDateTime();
177
178 OTimeZone zone(data->timezone );
179 return zone.toDateTime( data->end, OTimeZone::current() );
180}
181void OEvent::setEndDateTime( const QDateTime& dt ) {
182 changeOrModify();
183 data->end = dt;
184}
185bool OEvent::isMultipleDay()const {
186 return data->end.date().day() - data->start.date().day();
187}
188bool OEvent::isAllDay()const {
189 return data->isAllDay;
190}
191void OEvent::setTimeZone( const QString& tz ) {
192 changeOrModify();
193 data->timezone = tz;
194}
195QString OEvent::timeZone()const {
196 return data->timezone;
197}
198bool OEvent::match( const QRegExp& )const {
199 // FIXME
200 return false;
201}
202QString OEvent::toRichText()const {
203 // FIXME
204 return "OEvent test";
205}
206QString OEvent::toShortText()const {
207 return "OEvent shotText";
208}
209QString OEvent::type()const {
210 return QString::fromLatin1("OEvent");
211}
212QString OEvent::recordField( int /*id */ )const {
213 return QString::null;
214}
215int OEvent::rtti() {
216 return OPimResolver::DateBook;
217}
218bool OEvent::loadFromStream( QDataStream& ) {
219 return true;
220}
221bool OEvent::saveToStream( QDataStream& )const {
222 return true;
223}
224void OEvent::changeOrModify() {
225 if ( data->count != 1 ) {
226 data->deref();
227 Data* d2 = new Data;
228 d2->description = data->description;
229 d2->location = data->location;
230 d2->manager = data->manager;
231 d2->recur = data->recur;
232 d2->note = data->note;
233 d2->created = data->created;
234 d2->start = data->start;
235 d2->end = data->end;
236 d2->isAllDay = data->isAllDay;
237 d2->timezone = data->timezone;
238
239 data = d2;
240 }
241}
242void OEvent::deref() {
243 if ( data->deref() ) {
244 delete data;
245 data = 0;
246 }
247}
248// FIXME
249QMap<int, QString> OEvent::toMap()const {
250 return QMap<int, QString>();
251}
252QMap<QString, QString> OEvent::toExtraMap()const {
253 return QMap<QString, QString>();
254}
255
256
257struct OEffectiveEvent::Data : public QShared {
258 Data() : QShared() {
259 }
260 OEvent event;
261 QDate date;
262 QTime start, end;
263 QDate startDate, endDate;
264 bool dates : 1;
265};
266
267OEffectiveEvent::OEffectiveEvent() {
268 data = new Data;
269 data->date = QDate::currentDate();
270 data->start = data->end = QTime::currentTime();
271 data->dates = false;
272}
273OEffectiveEvent::OEffectiveEvent( const OEvent& ev, const QDate& startDate,
274 Position pos ) {
275 data = new Data;
276 data->event = ev;
277 data->date = startDate;
278 if ( pos & Start )
279 data->start = ev.startDateTime().time();
280 else
281 data->start = QTime( 0, 0, 0 );
282
283 if ( pos & End )
284 data->end = ev.endDateTime().time();
285 else
286 data->end = QTime( 23, 59, 59 );
287
288 data->dates = false;
289}
290OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) {
291 data = ev.data;
292 data->ref();
293}
294OEffectiveEvent::~OEffectiveEvent() {
295 if ( data->deref() ) {
296 delete data;
297 data = 0;
298 }
299}
300OEffectiveEvent& OEffectiveEvent::operator=( const OEffectiveEvent& ev ) {
301 if ( *this == ev ) return *this;
302
303 ev.data->ref();
304 deref();
305 data = ev.data;
306
307 return *this;
308}
309
310void OEffectiveEvent::setStartTime( const QTime& ti) {
311 changeOrModify();
312 data->start = ti;
313}
314void OEffectiveEvent::setEndTime( const QTime& en) {
315 changeOrModify();
316 data->end = en;
317}
318void OEffectiveEvent::setEvent( const OEvent& ev) {
319 changeOrModify();
320 data->event = ev;
321}
322void OEffectiveEvent::setDate( const QDate& da) {
323 changeOrModify();
324 data->date = da;
325}
326void OEffectiveEvent::setEffectiveDates( const QDate& from,
327 const QDate& to ) {
328 if (!from.isValid() ) {
329 data->dates = false;
330 return;
331 }
332
333 data->startDate = from;
334 data->endDate = to;
335}
336QString OEffectiveEvent::description()const {
337 return data->event.description();
338}
339QString OEffectiveEvent::location()const {
340 return data->event.location();
341}
342QString OEffectiveEvent::note()const {
343 return data->event.note();
344}
345OEvent OEffectiveEvent::event()const {
346 return data->event;
347}
348QTime OEffectiveEvent::startTime()const {
349 return data->start;
350}
351QTime OEffectiveEvent::endTime()const {
352 return data->end;
353}
354QDate OEffectiveEvent::date()const {
355 return data->date;
356}
357int OEffectiveEvent::length()const {
358 return (data->end.hour() * 60 - data->start.hour() * 60)
359 + QABS(data->start.minute() - data->end.minute() );
360}
361int OEffectiveEvent::size()const {
362 return ( data->end.hour() - data->start.hour() ) * 3600
363 + (data->end.minute() - data->start.minute() * 60
364 + data->end.second() - data->start.second() );
365}
366QDate OEffectiveEvent::startDate()const {
367 if ( data->dates )
368 return data->startDate;
369 else if ( data->event.hasRecurrence() ) // single day, since multi-day should have a d pointer
370 return data->date;
371 else
372 return data->event.startDateTime().date();
373}
374QDate OEffectiveEvent::endDate()const {
375 if ( data->dates )
376 return data->endDate;
377 else if ( data->event.hasRecurrence() )
378 return data->date;
379 else
380 return data->event.endDateTime().date();
381}
382void OEffectiveEvent::deref() {
383 if ( data->deref() ) {
384 delete data;
385 data = 0;
386 }
387}
388void OEffectiveEvent::changeOrModify() {
389 if ( data->count != 1 ) {
390 data->deref();
391 Data* d2 = new Data;
392 d2->event = data->event;
393 d2->date = data->date;
394 d2->start = data->start;
395 d2->end = data->end;
396 d2->startDate = data->startDate;
397 d2->endDate = data->endDate;
398 d2->dates = data->dates;
399 data = d2;
400 }
401}
402bool OEffectiveEvent::operator<( const OEffectiveEvent &e ) const{
403 if ( data->date < e.date() )
404 return TRUE;
405 if ( data->date == e.date() )
406 return ( startTime() < e.startTime() );
407 else
408 return FALSE;
409}
410bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{
411 return (data->date <= e.date() );
412}
413bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const {
414 return ( date() == e.date()
415 && startTime() == e.startTime()
416 && endTime()== e.endTime()
417 && event() == e.event() );
418}
419bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const {
420 return !(*this == e );
421}
422bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const {
423 return !(*this <= e );
424}
425bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const {
426 return !(*this < e);
427}
diff --git a/libopie2/opiepim/oevent.h b/libopie2/opiepim/oevent.h
new file mode 100644
index 0000000..4489be7
--- a/dev/null
+++ b/libopie2/opiepim/oevent.h
@@ -0,0 +1,198 @@
1// CONTAINS GPLed code of TT
2
3#ifndef OPIE_PIM_EVENT_H
4#define OPIE_PIM_EVENT_H
5
6#include <qstring.h>
7#include <qdatetime.h>
8#include <qvaluelist.h>
9
10#include <qpe/recordfields.h>
11#include <qpe/palmtopuidgen.h>
12
13#include "otimezone.h"
14#include "opimrecord.h"
15
16namespace OCalendarHelper {
17 /** calculate the week number of the date */
18 static int week( const QDate& );
19 /** calculate the occurence of week days since the start of the month */
20 static int ocurrence( const QDate& );
21
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
24 static int dayOfWeek( char day );
25
26 /** returns the diff of month */
27 static int monthDiff( const QDate& first, const QDate& second );
28
29}
30
31class OPimNotifyManager;
32class ORecur;
33class OEvent : public OPimRecord {
34public:
35 typedef QValueList<OEvent> ValueList;
36 enum RecordFields {
37 Uid = Qtopia::UID_ID,
38 Category = Qtopia::CATEGORY_ID,
39 Description,
40 Location,
41 Alarm,
42 Reminder,
43 Recurrence,
44 Note,
45 Created,
46 StartDate,
47 EndDate,
48 AllDay,
49 TimeZone
50 };
51
52 OEvent(int uid = 0);
53 OEvent( const OEvent& );
54 ~OEvent();
55 OEvent &operator=( const OEvent& );
56
57 QString description()const;
58 void setDescription( const QString& description );
59
60 QString location()const;
61 void setLocation( const QString& loc );
62
63 bool hasNotifiers()const;
64 OPimNotifyManager &notifiers();
65
66 ORecur recurrence()const;
67 void setRecurrence( const ORecur& );
68 bool hasRecurrence()const;
69
70 QString note()const;
71 void setNote( const QString& note );
72
73
74 QDateTime createdDateTime()const;
75 void setCreatedDateTime( const QDateTime& dt);
76
77 /** set the date to dt. dt is the QDateTime in localtime */
78 void setStartDateTime( const QDateTime& );
79 /** returns the datetime in the local timeZone */
80 QDateTime startDateTime()const;
81
82 /** returns the start datetime in the current zone */
83 QDateTime startDateTimeInZone()const;
84
85 /** in current timezone */
86 void setEndDateTime( const QDateTime& );
87 /** in current timezone */
88 QDateTime endDateTime()const;
89 QDateTime endDateTimeInZone()const;
90
91 bool isMultipleDay()const;
92 bool isAllDay()const;
93 void setAllDay( bool isAllDay );
94
95 /* pin this event to a timezone! FIXME */
96 void setTimeZone( const QString& timeZone );
97 QString timeZone()const;
98
99
100 bool match( const QRegExp& )const;
101
102
103
104
105 /* needed reimp */
106 QString toRichText()const;
107 QString toShortText()const;
108 QString type()const;
109
110 QMap<int, QString> toMap()const;
111 QMap<QString, QString> toExtraMap()const;
112 QString recordField(int )const;
113
114 static int rtti();
115
116 bool loadFromStream( QDataStream& );
117 bool saveToStream( QDataStream& )const;
118
119/* bool operator==( const OEvent& );
120 bool operator!=( const OEvent& );
121 bool operator<( const OEvent& );
122 bool operator<=( const OEvent& );
123 bool operator>( const OEvent& );
124 bool operator>=(const OEvent& );
125*/
126private:
127 inline void changeOrModify();
128 void deref();
129 struct Data;
130 Data* data;
131 class Private;
132 Private* priv;
133
134};
135
136/**
137 * AN Event can span through multiple days. We split up a multiday eve
138 */
139
140class OEffectiveEvent {
141public:
142 QValueList<OEffectiveEvent> ValueList;
143 enum Position { MidWay, Start, End, StartEnd };
144 // If we calculate the effective event of a multi-day event
145 // we have to figure out whether we are at the first day,
146 // at the end, or anywhere else ("middle"). This is important
147 // for the start/end times (00:00/23:59)
148 // MidWay: 00:00 -> 23:59, as we are "in the middle" of a multi-
149 // day event
150 // Start: start time -> 23:59
151 // End: 00:00 -> end time
152 // Start | End == StartEnd: for single-day events (default)
153 // here we draw start time -> end time
154 OEffectiveEvent();
155 OEffectiveEvent( const OEvent& event, const QDate& startDate, Position pos = StartEnd );
156 OEffectiveEvent( const OEffectiveEvent& );
157 OEffectiveEvent &operator=(const OEffectiveEvent& );
158 ~OEffectiveEvent();
159
160 void setStartTime( const QTime& );
161 void setEndTime( const QTime& );
162 void setEvent( const OEvent& );
163 void setDate( const QDate& );
164
165 void setEffectiveDates( const QDate& from, const QDate& to );
166
167 QString description()const;
168 QString location()const;
169 QString note()const;
170 OEvent event()const;
171 QTime startTime()const;
172 QTime endTime()const;
173 QDate date()const;
174
175 /* return the length in hours */
176 int length()const;
177 int size()const;
178
179 QDate startDate()const;
180 QDate endDate()const;
181
182 bool operator<( const OEffectiveEvent &e ) const;
183 bool operator<=( const OEffectiveEvent &e ) const;
184 bool operator==( const OEffectiveEvent &e ) const;
185 bool operator!=( const OEffectiveEvent &e ) const;
186 bool operator>( const OEffectiveEvent &e ) const;
187 bool operator>= ( const OEffectiveEvent &e ) const;
188
189private:
190 void deref();
191 inline void changeOrModify();
192 class Private;
193 Private* priv;
194 struct Data;
195 Data* data;
196
197};
198#endif
diff --git a/libopie2/opiepim/otodo.cpp b/libopie2/opiepim/otodo.cpp
index b4d4aa9..049359e 100644
--- a/libopie2/opiepim/otodo.cpp
+++ b/libopie2/opiepim/otodo.cpp
@@ -247,176 +247,178 @@ QString OTodo::toRichText() const
247 text += "<b>" + QObject::tr( "Priority:") +" </b>" 247 text += "<b>" + QObject::tr( "Priority:") +" </b>"
248 + QString::number( priority() ) + " <br>"; 248 + QString::number( priority() ) + " <br>";
249 text += "<b>" + QObject::tr( "Progress:") + " </b>" 249 text += "<b>" + QObject::tr( "Progress:") + " </b>"
250 + QString::number( progress() ) + " %<br>"; 250 + QString::number( progress() ) + " %<br>";
251 if (hasDueDate() ){ 251 if (hasDueDate() ){
252 text += "<b>" + QObject::tr( "Deadline:") + " </b>"; 252 text += "<b>" + QObject::tr( "Deadline:") + " </b>";
253 text += dueDate().toString(); 253 text += dueDate().toString();
254 text += "<br>"; 254 text += "<br>";
255 } 255 }
256 256
257 text += "<b>" + QObject::tr( "Category:") + "</b> "; 257 text += "<b>" + QObject::tr( "Category:") + "</b> ";
258 text += categoryNames( "Todo List" ).join(", "); 258 text += categoryNames( "Todo List" ).join(", ");
259 text += "<br>"; 259 text += "<br>";
260 260
261 return text; 261 return text;
262} 262}
263OPimNotifyManager& OTodo::notifiers() { 263OPimNotifyManager& OTodo::notifiers() {
264 return data->notifiers; 264 return data->notifiers;
265} 265}
266 266
267bool OTodo::operator<( const OTodo &toDoEvent )const{ 267bool OTodo::operator<( const OTodo &toDoEvent )const{
268 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true; 268 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
269 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false; 269 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
270 if( hasDueDate() && toDoEvent.hasDueDate() ){ 270 if( hasDueDate() && toDoEvent.hasDueDate() ){
271 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide 271 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
272 return priority() < toDoEvent.priority(); 272 return priority() < toDoEvent.priority();
273 }else{ 273 }else{
274 return dueDate() < toDoEvent.dueDate(); 274 return dueDate() < toDoEvent.dueDate();
275 } 275 }
276 } 276 }
277 return false; 277 return false;
278} 278}
279bool OTodo::operator<=(const OTodo &toDoEvent )const 279bool OTodo::operator<=(const OTodo &toDoEvent )const
280{ 280{
281 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true; 281 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
282 if( !hasDueDate() && toDoEvent.hasDueDate() ) return true; 282 if( !hasDueDate() && toDoEvent.hasDueDate() ) return true;
283 if( hasDueDate() && toDoEvent.hasDueDate() ){ 283 if( hasDueDate() && toDoEvent.hasDueDate() ){
284 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide 284 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
285 return priority() <= toDoEvent.priority(); 285 return priority() <= toDoEvent.priority();
286 }else{ 286 }else{
287 return dueDate() <= toDoEvent.dueDate(); 287 return dueDate() <= toDoEvent.dueDate();
288 } 288 }
289 } 289 }
290 return true; 290 return true;
291} 291}
292bool OTodo::operator>(const OTodo &toDoEvent )const 292bool OTodo::operator>(const OTodo &toDoEvent )const
293{ 293{
294 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return false; 294 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return false;
295 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false; 295 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
296 if( hasDueDate() && toDoEvent.hasDueDate() ){ 296 if( hasDueDate() && toDoEvent.hasDueDate() ){
297 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide 297 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
298 return priority() > toDoEvent.priority(); 298 return priority() > toDoEvent.priority();
299 }else{ 299 }else{
300 return dueDate() > toDoEvent.dueDate(); 300 return dueDate() > toDoEvent.dueDate();
301 } 301 }
302 } 302 }
303 return false; 303 return false;
304} 304}
305bool OTodo::operator>=(const OTodo &toDoEvent )const 305bool OTodo::operator>=(const OTodo &toDoEvent )const
306{ 306{
307 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true; 307 if( !hasDueDate() && !toDoEvent.hasDueDate() ) return true;
308 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false; 308 if( !hasDueDate() && toDoEvent.hasDueDate() ) return false;
309 if( hasDueDate() && toDoEvent.hasDueDate() ){ 309 if( hasDueDate() && toDoEvent.hasDueDate() ){
310 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide 310 if( dueDate() == toDoEvent.dueDate() ){ // let's the priority decide
311 return priority() > toDoEvent.priority(); 311 return priority() > toDoEvent.priority();
312 }else{ 312 }else{
313 return dueDate() > toDoEvent.dueDate(); 313 return dueDate() > toDoEvent.dueDate();
314 } 314 }
315 } 315 }
316 return true; 316 return true;
317} 317}
318bool OTodo::operator==(const OTodo &toDoEvent )const 318bool OTodo::operator==(const OTodo &toDoEvent )const
319{ 319{
320 if ( data->priority != toDoEvent.data->priority ) return false; 320 if ( data->priority != toDoEvent.data->priority ) return false;
321 if ( data->priority != toDoEvent.data->prog ) return false; 321 if ( data->priority != toDoEvent.data->prog ) return false;
322 if ( data->isCompleted != toDoEvent.data->isCompleted ) return false; 322 if ( data->isCompleted != toDoEvent.data->isCompleted ) return false;
323 if ( data->hasDate != toDoEvent.data->hasDate ) return false; 323 if ( data->hasDate != toDoEvent.data->hasDate ) return false;
324 if ( data->date != toDoEvent.data->date ) return false; 324 if ( data->date != toDoEvent.data->date ) return false;
325 if ( data->sum != toDoEvent.data->sum ) return false; 325 if ( data->sum != toDoEvent.data->sum ) return false;
326 if ( data->desc != toDoEvent.data->desc ) return false; 326 if ( data->desc != toDoEvent.data->desc ) return false;
327 if ( data->maintainer != toDoEvent.data->maintainer ) 327 if ( data->maintainer != toDoEvent.data->maintainer )
328 return false; 328 return false;
329 329
330 return OPimRecord::operator==( toDoEvent ); 330 return OPimRecord::operator==( toDoEvent );
331} 331}
332void OTodo::deref() { 332void OTodo::deref() {
333 333
334// qWarning("deref in ToDoEvent"); 334// qWarning("deref in ToDoEvent");
335 if ( data->deref() ) { 335 if ( data->deref() ) {
336// qWarning("deleting"); 336// qWarning("deleting");
337 delete data; 337 delete data;
338 data= 0; 338 data= 0;
339 } 339 }
340} 340}
341OTodo &OTodo::operator=(const OTodo &item ) 341OTodo &OTodo::operator=(const OTodo &item )
342{ 342{
343 if ( *this == item ) return *this;
344
343 OPimRecord::operator=( item ); 345 OPimRecord::operator=( item );
344 //qWarning("operator= ref "); 346 //qWarning("operator= ref ");
345 item.data->ref(); 347 item.data->ref();
346 deref(); 348 deref();
347 data = item.data; 349 data = item.data;
348 350
349 return *this; 351 return *this;
350} 352}
351 353
352QMap<int, QString> OTodo::toMap() const { 354QMap<int, QString> OTodo::toMap() const {
353 QMap<int, QString> map; 355 QMap<int, QString> map;
354 356
355 map.insert( Uid, QString::number( uid() ) ); 357 map.insert( Uid, QString::number( uid() ) );
356 map.insert( Category, idsToString( categories() ) ); 358 map.insert( Category, idsToString( categories() ) );
357 map.insert( HasDate, QString::number( data->hasDate ) ); 359 map.insert( HasDate, QString::number( data->hasDate ) );
358 map.insert( Completed, QString::number( data->isCompleted ) ); 360 map.insert( Completed, QString::number( data->isCompleted ) );
359 map.insert( Description, data->desc ); 361 map.insert( Description, data->desc );
360 map.insert( Summary, data->sum ); 362 map.insert( Summary, data->sum );
361 map.insert( Priority, QString::number( data->priority ) ); 363 map.insert( Priority, QString::number( data->priority ) );
362 map.insert( DateDay, QString::number( data->date.day() ) ); 364 map.insert( DateDay, QString::number( data->date.day() ) );
363 map.insert( DateMonth, QString::number( data->date.month() ) ); 365 map.insert( DateMonth, QString::number( data->date.month() ) );
364 map.insert( DateYear, QString::number( data->date.year() ) ); 366 map.insert( DateYear, QString::number( data->date.year() ) );
365 map.insert( Progress, QString::number( data->prog ) ); 367 map.insert( Progress, QString::number( data->prog ) );
366// map.insert( CrossReference, crossToString() ); 368// map.insert( CrossReference, crossToString() );
367 /* FIXME!!! map.insert( State, ); 369 /* FIXME!!! map.insert( State, );
368 map.insert( Recurrence, ); 370 map.insert( Recurrence, );
369 map.insert( Reminders, ); 371 map.insert( Reminders, );
370 map. 372 map.
371 */ 373 */
372 return map; 374 return map;
373} 375}
374 376
375QMap<QString, QString> OTodo::toExtraMap()const { 377QMap<QString, QString> OTodo::toExtraMap()const {
376 return data->extra; 378 return data->extra;
377} 379}
378/** 380/**
379 * change or modify looks at the ref count and either 381 * change or modify looks at the ref count and either
380 * creates a new QShared Object or it can modify it 382 * creates a new QShared Object or it can modify it
381 * right in place 383 * right in place
382 */ 384 */
383void OTodo::changeOrModify() { 385void OTodo::changeOrModify() {
384 if ( data->count != 1 ) { 386 if ( data->count != 1 ) {
385 qWarning("changeOrModify"); 387 qWarning("changeOrModify");
386 data->deref(); 388 data->deref();
387 OTodoData* d2 = new OTodoData(); 389 OTodoData* d2 = new OTodoData();
388 copy(data, d2 ); 390 copy(data, d2 );
389 data = d2; 391 data = d2;
390 } 392 }
391} 393}
392// WATCHOUT 394// WATCHOUT
393/* 395/*
394 * if you add something to the Data struct 396 * if you add something to the Data struct
395 * be sure to copy it here 397 * be sure to copy it here
396 */ 398 */
397void OTodo::copy( OTodoData* src, OTodoData* dest ) { 399void OTodo::copy( OTodoData* src, OTodoData* dest ) {
398 dest->date = src->date; 400 dest->date = src->date;
399 dest->isCompleted = src->isCompleted; 401 dest->isCompleted = src->isCompleted;
400 dest->hasDate = src->hasDate; 402 dest->hasDate = src->hasDate;
401 dest->priority = src->priority; 403 dest->priority = src->priority;
402 dest->desc = src->desc; 404 dest->desc = src->desc;
403 dest->sum = src->sum; 405 dest->sum = src->sum;
404 dest->extra = src->extra; 406 dest->extra = src->extra;
405 dest->prog = src->prog; 407 dest->prog = src->prog;
406 dest->state = src->state; 408 dest->state = src->state;
407 dest->recur = src->recur; 409 dest->recur = src->recur;
408 dest->maintainer = src->maintainer; 410 dest->maintainer = src->maintainer;
409 dest->start = src->start; 411 dest->start = src->start;
410 dest->completed = src->completed; 412 dest->completed = src->completed;
411 dest->notifiers = src->notifiers; 413 dest->notifiers = src->notifiers;
412} 414}
413QString OTodo::type() const { 415QString OTodo::type() const {
414 return QString::fromLatin1("OTodo"); 416 return QString::fromLatin1("OTodo");
415} 417}
416QString OTodo::recordField(int /*id*/ )const { 418QString OTodo::recordField(int /*id*/ )const {
417 return QString::null; 419 return QString::null;
418} 420}
419 421
420int OTodo::rtti(){ 422int OTodo::rtti(){
421 return OPimResolver::TodoList; 423 return OPimResolver::TodoList;
422} 424}