-rw-r--r-- | libopie2/opiepim/oevent.cpp | 427 |
1 files changed, 427 insertions, 0 deletions
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 | |||
12 | namespace 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 | |||
45 | struct 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 | |||
67 | OEvent::OEvent( int uid ) | ||
68 | : OPimRecord( uid ) { | ||
69 | data = new Data; | ||
70 | } | ||
71 | OEvent::OEvent( const OEvent& ev) | ||
72 | : OPimRecord( ev ), data( ev.data ) | ||
73 | { | ||
74 | data->ref(); | ||
75 | } | ||
76 | OEvent::~OEvent() { | ||
77 | if ( data->deref() ) { | ||
78 | delete data; | ||
79 | data = 0; | ||
80 | } | ||
81 | } | ||
82 | OEvent& 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 | } | ||
93 | QString OEvent::description()const { | ||
94 | return data->description; | ||
95 | } | ||
96 | void OEvent::setDescription( const QString& description ) { | ||
97 | changeOrModify(); | ||
98 | data->description = description; | ||
99 | } | ||
100 | void OEvent::setLocation( const QString& loc ) { | ||
101 | changeOrModify(); | ||
102 | data->location = loc; | ||
103 | } | ||
104 | QString OEvent::location()const { | ||
105 | return data->location; | ||
106 | } | ||
107 | OPimNotifyManager &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 | } | ||
116 | bool OEvent::hasNotifiers()const { | ||
117 | return ( data->manager); | ||
118 | } | ||
119 | ORecur OEvent::recurrence()const { | ||
120 | if (!data->recur) | ||
121 | data->recur = new ORecur; | ||
122 | |||
123 | return *data->recur; | ||
124 | } | ||
125 | void OEvent::setRecurrence( const ORecur& rec) { | ||
126 | changeOrModify(); | ||
127 | if (data->recur ) | ||
128 | (*data->recur) = rec; | ||
129 | else | ||
130 | data->recur = new ORecur( rec ); | ||
131 | } | ||
132 | bool OEvent::hasRecurrence()const { | ||
133 | return data->recur; | ||
134 | } | ||
135 | QString OEvent::note()const { | ||
136 | return data->note; | ||
137 | } | ||
138 | void OEvent::setNote( const QString& note ) { | ||
139 | changeOrModify(); | ||
140 | data->note = note; | ||
141 | } | ||
142 | QDateTime OEvent::createdDateTime()const { | ||
143 | return data->created; | ||
144 | } | ||
145 | void OEvent::setCreatedDateTime( const QDateTime& time ) { | ||
146 | changeOrModify(); | ||
147 | data->created = time; | ||
148 | } | ||
149 | QDateTime OEvent::startDateTime()const { | ||
150 | if ( data->isAllDay ) | ||
151 | return QDateTime( data->start.date(), QTime(0, 0, 0 ) ); | ||
152 | return data->start; | ||
153 | } | ||
154 | QDateTime 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 | } | ||
161 | void OEvent::setStartDateTime( const QDateTime& dt ) { | ||
162 | changeOrModify(); | ||
163 | data->start = dt; | ||
164 | } | ||
165 | QDateTime 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 | } | ||
174 | QDateTime 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 | } | ||
181 | void OEvent::setEndDateTime( const QDateTime& dt ) { | ||
182 | changeOrModify(); | ||
183 | data->end = dt; | ||
184 | } | ||
185 | bool OEvent::isMultipleDay()const { | ||
186 | return data->end.date().day() - data->start.date().day(); | ||
187 | } | ||
188 | bool OEvent::isAllDay()const { | ||
189 | return data->isAllDay; | ||
190 | } | ||
191 | void OEvent::setTimeZone( const QString& tz ) { | ||
192 | changeOrModify(); | ||
193 | data->timezone = tz; | ||
194 | } | ||
195 | QString OEvent::timeZone()const { | ||
196 | return data->timezone; | ||
197 | } | ||
198 | bool OEvent::match( const QRegExp& )const { | ||
199 | // FIXME | ||
200 | return false; | ||
201 | } | ||
202 | QString OEvent::toRichText()const { | ||
203 | // FIXME | ||
204 | return "OEvent test"; | ||
205 | } | ||
206 | QString OEvent::toShortText()const { | ||
207 | return "OEvent shotText"; | ||
208 | } | ||
209 | QString OEvent::type()const { | ||
210 | return QString::fromLatin1("OEvent"); | ||
211 | } | ||
212 | QString OEvent::recordField( int /*id */ )const { | ||
213 | return QString::null; | ||
214 | } | ||
215 | int OEvent::rtti() { | ||
216 | return OPimResolver::DateBook; | ||
217 | } | ||
218 | bool OEvent::loadFromStream( QDataStream& ) { | ||
219 | return true; | ||
220 | } | ||
221 | bool OEvent::saveToStream( QDataStream& )const { | ||
222 | return true; | ||
223 | } | ||
224 | void 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 | } | ||
242 | void OEvent::deref() { | ||
243 | if ( data->deref() ) { | ||
244 | delete data; | ||
245 | data = 0; | ||
246 | } | ||
247 | } | ||
248 | // FIXME | ||
249 | QMap<int, QString> OEvent::toMap()const { | ||
250 | return QMap<int, QString>(); | ||
251 | } | ||
252 | QMap<QString, QString> OEvent::toExtraMap()const { | ||
253 | return QMap<QString, QString>(); | ||
254 | } | ||
255 | |||
256 | |||
257 | struct 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 | |||
267 | OEffectiveEvent::OEffectiveEvent() { | ||
268 | data = new Data; | ||
269 | data->date = QDate::currentDate(); | ||
270 | data->start = data->end = QTime::currentTime(); | ||
271 | data->dates = false; | ||
272 | } | ||
273 | OEffectiveEvent::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 | } | ||
290 | OEffectiveEvent::OEffectiveEvent( const OEffectiveEvent& ev) { | ||
291 | data = ev.data; | ||
292 | data->ref(); | ||
293 | } | ||
294 | OEffectiveEvent::~OEffectiveEvent() { | ||
295 | if ( data->deref() ) { | ||
296 | delete data; | ||
297 | data = 0; | ||
298 | } | ||
299 | } | ||
300 | OEffectiveEvent& 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 | |||
310 | void OEffectiveEvent::setStartTime( const QTime& ti) { | ||
311 | changeOrModify(); | ||
312 | data->start = ti; | ||
313 | } | ||
314 | void OEffectiveEvent::setEndTime( const QTime& en) { | ||
315 | changeOrModify(); | ||
316 | data->end = en; | ||
317 | } | ||
318 | void OEffectiveEvent::setEvent( const OEvent& ev) { | ||
319 | changeOrModify(); | ||
320 | data->event = ev; | ||
321 | } | ||
322 | void OEffectiveEvent::setDate( const QDate& da) { | ||
323 | changeOrModify(); | ||
324 | data->date = da; | ||
325 | } | ||
326 | void 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 | } | ||
336 | QString OEffectiveEvent::description()const { | ||
337 | return data->event.description(); | ||
338 | } | ||
339 | QString OEffectiveEvent::location()const { | ||
340 | return data->event.location(); | ||
341 | } | ||
342 | QString OEffectiveEvent::note()const { | ||
343 | return data->event.note(); | ||
344 | } | ||
345 | OEvent OEffectiveEvent::event()const { | ||
346 | return data->event; | ||
347 | } | ||
348 | QTime OEffectiveEvent::startTime()const { | ||
349 | return data->start; | ||
350 | } | ||
351 | QTime OEffectiveEvent::endTime()const { | ||
352 | return data->end; | ||
353 | } | ||
354 | QDate OEffectiveEvent::date()const { | ||
355 | return data->date; | ||
356 | } | ||
357 | int OEffectiveEvent::length()const { | ||
358 | return (data->end.hour() * 60 - data->start.hour() * 60) | ||
359 | + QABS(data->start.minute() - data->end.minute() ); | ||
360 | } | ||
361 | int 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 | } | ||
366 | QDate 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 | } | ||
374 | QDate 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 | } | ||
382 | void OEffectiveEvent::deref() { | ||
383 | if ( data->deref() ) { | ||
384 | delete data; | ||
385 | data = 0; | ||
386 | } | ||
387 | } | ||
388 | void 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 | } | ||
402 | bool 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 | } | ||
410 | bool OEffectiveEvent::operator<=( const OEffectiveEvent &e ) const{ | ||
411 | return (data->date <= e.date() ); | ||
412 | } | ||
413 | bool OEffectiveEvent::operator==( const OEffectiveEvent &e ) const { | ||
414 | return ( date() == e.date() | ||
415 | && startTime() == e.startTime() | ||
416 | && endTime()== e.endTime() | ||
417 | && event() == e.event() ); | ||
418 | } | ||
419 | bool OEffectiveEvent::operator!=( const OEffectiveEvent &e ) const { | ||
420 | return !(*this == e ); | ||
421 | } | ||
422 | bool OEffectiveEvent::operator>( const OEffectiveEvent &e ) const { | ||
423 | return !(*this <= e ); | ||
424 | } | ||
425 | bool OEffectiveEvent::operator>= ( const OEffectiveEvent &e ) const { | ||
426 | return !(*this < e); | ||
427 | } | ||