-rw-r--r-- | library/backend/event.cpp | 830 |
1 files changed, 830 insertions, 0 deletions
diff --git a/library/backend/event.cpp b/library/backend/event.cpp new file mode 100644 index 0000000..50a663d --- a/dev/null +++ b/library/backend/event.cpp | |||
@@ -0,0 +1,830 @@ | |||
1 | /********************************************************************** | ||
2 | ** Copyright (C) 2001 Trolltech AS. All rights reserved. | ||
3 | ** | ||
4 | ** This file is part of Qtopia Environment. | ||
5 | ** | ||
6 | ** This file may be distributed and/or modified under the terms of the | ||
7 | ** GNU General Public License version 2 as published by the Free Software | ||
8 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
9 | ** packaging of this file. | ||
10 | ** | ||
11 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
12 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
13 | ** | ||
14 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
15 | ** | ||
16 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
17 | ** not clear to you. | ||
18 | ** | ||
19 | **********************************************************************/ | ||
20 | |||
21 | #include "event.h" | ||
22 | #include "qfiledirect_p.h" | ||
23 | #include <qpe/timeconversion.h> | ||
24 | #include <qpe/stringutil.h> | ||
25 | #include <qpe/recordfields.h> | ||
26 | #include <qbuffer.h> | ||
27 | #include <time.h> | ||
28 | #include "vobject_p.h" | ||
29 | |||
30 | #include <stdio.h> | ||
31 | |||
32 | using namespace Qtopia; | ||
33 | |||
34 | static void write( QString& buf, const Event::RepeatPattern &r ) | ||
35 | { | ||
36 | buf += " rtype=\""; | ||
37 | switch ( r.type ) { | ||
38 | case Event::Daily: | ||
39 | buf += "Daily"; | ||
40 | break; | ||
41 | case Event::Weekly: | ||
42 | buf += "Weekly"; | ||
43 | break; | ||
44 | case Event::MonthlyDay: | ||
45 | buf += "MonthlyDay"; | ||
46 | break; | ||
47 | case Event::MonthlyDate: | ||
48 | buf += "MonthlyDate"; | ||
49 | break; | ||
50 | case Event::Yearly: | ||
51 | buf += "Yearly"; | ||
52 | break; | ||
53 | default: | ||
54 | buf += "NoRepeat"; | ||
55 | break; | ||
56 | } | ||
57 | buf += "\""; | ||
58 | if ( r.days > 0 ) | ||
59 | buf += " rweekdays=\"" + QString::number( static_cast<int>( r.days ) ) + "\""; | ||
60 | if ( r.position != 0 ) | ||
61 | buf += " rposition=\"" + QString::number( r.position ) + "\""; | ||
62 | |||
63 | buf += " rfreq=\"" + QString::number( r.frequency ) + "\""; | ||
64 | buf += " rhasenddate=\"" + QString::number( static_cast<int>( r.hasEndDate ) ) + "\""; | ||
65 | if ( r.hasEndDate ) | ||
66 | buf += " enddt=\"" | ||
67 | + QString::number( r.endDateUTC ? r.endDateUTC : time( 0 ) ) | ||
68 | + "\""; | ||
69 | buf += " created=\"" + QString::number( r.createTime ) + "\""; | ||
70 | } | ||
71 | |||
72 | Qtopia::UidGen Event::sUidGen( Qtopia::UidGen::Qtopia ); | ||
73 | |||
74 | Event::Event() : Record() | ||
75 | { | ||
76 | startUTC = endUTC = time( 0 ); | ||
77 | typ = Normal; | ||
78 | hAlarm = FALSE; | ||
79 | hRepeat = FALSE; | ||
80 | aMinutes = 0; | ||
81 | aSound = Silent; | ||
82 | pattern.type = NoRepeat; | ||
83 | pattern.frequency = -1; | ||
84 | } | ||
85 | |||
86 | Event::Event( const QMap<int, QString> &map ) | ||
87 | { | ||
88 | setDescription( map[DatebookDescription] ); | ||
89 | setLocation( map[Location] ); | ||
90 | setCategories( idsFromString( map[DatebookCategory] ) ); | ||
91 | setTimeZone( map[TimeZone] ); | ||
92 | setNotes( map[Note] ); | ||
93 | setStart( TimeConversion::fromUTC( map[StartDateTime].toUInt() ) ); | ||
94 | setEnd( TimeConversion::fromUTC( map[EndDateTime].toUInt() ) ); | ||
95 | setType( (Event::Type) map[DatebookType].toInt() ); | ||
96 | setAlarm( ( map[HasAlarm] == "1" ? TRUE : FALSE ), map[AlarmTime].toInt(), (Event::SoundTypeChoice)map[SoundType].toInt() ); | ||
97 | Event::RepeatPattern p; | ||
98 | p.type = (Event::RepeatType) map[ RepeatPatternType ].toInt(); | ||
99 | p.frequency = map[ RepeatPatternFrequency ].toInt(); | ||
100 | p.position = map[ RepeatPatternPosition ].toInt(); | ||
101 | p.days = map[ RepeatPatternDays ].toInt(); | ||
102 | p.hasEndDate = map[ RepeatPatternHasEndDate ].toInt(); | ||
103 | p.endDateUTC = map[ RepeatPatternEndDate ].toUInt(); | ||
104 | setRepeat( p ); | ||
105 | |||
106 | setUid( map[ DatebookUid ].toInt() ); | ||
107 | } | ||
108 | |||
109 | Event::~Event() | ||
110 | { | ||
111 | } | ||
112 | |||
113 | int Event::week( const QDate& date ) | ||
114 | { | ||
115 | // Calculates the week this date is in within that | ||
116 | // month. Equals the "row" is is in in the month view | ||
117 | int week = 1; | ||
118 | QDate tmp( date.year(), date.month(), 1 ); | ||
119 | |||
120 | if ( date.dayOfWeek() < tmp.dayOfWeek() ) | ||
121 | ++week; | ||
122 | |||
123 | week += ( date.day() - 1 ) / 7; | ||
124 | return week; | ||
125 | } | ||
126 | |||
127 | int Event::occurrence( const QDate& date ) | ||
128 | { | ||
129 | // calculates the number of occurrances of this day of the | ||
130 | // week till the given date (e.g 3rd Wednesday of the month) | ||
131 | return ( date.day() - 1 ) / 7 + 1; | ||
132 | } | ||
133 | |||
134 | int Event::dayOfWeek( char day ) | ||
135 | { | ||
136 | int dayOfWeek = 1; | ||
137 | char i = Event::MON; | ||
138 | while ( !( i & day ) && i <= Event::SUN ) { | ||
139 | i <<= 1; | ||
140 | ++dayOfWeek; | ||
141 | } | ||
142 | return dayOfWeek; | ||
143 | } | ||
144 | |||
145 | int Event::monthDiff( const QDate& first, const QDate& second ) | ||
146 | { | ||
147 | return ( second.year() - first.year() ) * 12 + | ||
148 | second.month() - first.month(); | ||
149 | } | ||
150 | |||
151 | QMap<int, QString> Event::toMap() const | ||
152 | { | ||
153 | QMap<int, QString> m; | ||
154 | m.insert( DatebookDescription, description() ); | ||
155 | m.insert ( Location, location() ); | ||
156 | m.insert ( DatebookCategory, idsToString( categories() ) ); | ||
157 | m.insert ( TimeZone, timeZone() ); | ||
158 | m.insert ( Note, notes() ); | ||
159 | m.insert ( StartDateTime, QString::number( TimeConversion::toUTC( start() ) ) ); | ||
160 | m.insert ( EndDateTime, QString::number( TimeConversion::toUTC( end() ) ) ); | ||
161 | m.insert ( DatebookType, QString::number( (int)type() ) ); | ||
162 | m.insert ( HasAlarm, ( hasAlarm() ? "1" : "0" ) ); | ||
163 | m.insert ( SoundType, QString::number( (int)alarmSound() ) ); | ||
164 | m.insert ( AlarmTime, QString::number( alarmTime() ) ); | ||
165 | m.insert ( RepeatPatternType, QString::number( static_cast<int>( repeatPattern().type ) ) ); | ||
166 | m.insert ( RepeatPatternFrequency, QString::number( repeatPattern().frequency ) ); | ||
167 | m.insert ( RepeatPatternPosition, QString::number( repeatPattern().position ) ); | ||
168 | m.insert ( RepeatPatternDays, QString::number( repeatPattern().days ) ); | ||
169 | m.insert ( RepeatPatternHasEndDate, QString::number( static_cast<int>( repeatPattern().hasEndDate ) ) ); | ||
170 | m.insert ( RepeatPatternEndDate, QString::number( repeatPattern().endDateUTC ) ); | ||
171 | |||
172 | m.insert( DatebookUid, QString::number( uid()) ); | ||
173 | |||
174 | return m; | ||
175 | } | ||
176 | |||
177 | void Event::setRepeat( const RepeatPattern &p ) | ||
178 | { | ||
179 | setRepeat( p.type != NoRepeat, p ); | ||
180 | } | ||
181 | |||
182 | void Event::setDescription( const QString &s ) | ||
183 | { | ||
184 | descript = s; | ||
185 | } | ||
186 | |||
187 | void Event::setLocation( const QString &s ) | ||
188 | { | ||
189 | locat = s; | ||
190 | } | ||
191 | |||
192 | // void Event::setCategory( const QString &s ) | ||
193 | // { | ||
194 | // categ = s; | ||
195 | // } | ||
196 | |||
197 | void Event::setType( Type t ) | ||
198 | { | ||
199 | typ = t; | ||
200 | } | ||
201 | |||
202 | void Event::setStart( const QDateTime &d ) | ||
203 | { | ||
204 | startUTC = TimeConversion::toUTC( d ); | ||
205 | } | ||
206 | |||
207 | void Event::setStart( time_t time ) | ||
208 | { | ||
209 | startUTC = time; | ||
210 | } | ||
211 | |||
212 | void Event::setEnd( const QDateTime &d ) | ||
213 | { | ||
214 | endUTC = TimeConversion::toUTC( d ); | ||
215 | } | ||
216 | |||
217 | void Event::setEnd( time_t time ) | ||
218 | { | ||
219 | endUTC = time; | ||
220 | } | ||
221 | |||
222 | void Event::setTimeZone( const QString &z ) | ||
223 | { | ||
224 | tz = z; | ||
225 | } | ||
226 | |||
227 | void Event::setAlarm( bool b, int minutes, SoundTypeChoice s ) | ||
228 | { | ||
229 | hAlarm = b; | ||
230 | aMinutes = minutes; | ||
231 | aSound = s; | ||
232 | } | ||
233 | |||
234 | void Event::setRepeat( bool b, const RepeatPattern &p ) | ||
235 | { | ||
236 | hRepeat = b; | ||
237 | pattern = p; | ||
238 | } | ||
239 | |||
240 | void Event::setNotes( const QString &n ) | ||
241 | { | ||
242 | note = n; | ||
243 | } | ||
244 | |||
245 | const QString &Event::description() const | ||
246 | { | ||
247 | return descript; | ||
248 | } | ||
249 | |||
250 | const QString &Event::location() const | ||
251 | { | ||
252 | return locat; | ||
253 | } | ||
254 | |||
255 | // QString Event::category() const | ||
256 | // { | ||
257 | // return categ; | ||
258 | // } | ||
259 | |||
260 | Event::Type Event::type() const | ||
261 | { | ||
262 | return typ; | ||
263 | } | ||
264 | |||
265 | QDateTime Event::start( bool actual ) const | ||
266 | { | ||
267 | QDateTime dt = (startUTC > 0) ? TimeConversion::fromUTC( startUTC ) : QDateTime::currentDateTime(); | ||
268 | |||
269 | if ( actual && typ == AllDay ) { | ||
270 | QTime t = dt.time(); | ||
271 | t.setHMS( 0, 0, 0 ); | ||
272 | dt.setTime( t ); | ||
273 | } | ||
274 | return dt; | ||
275 | } | ||
276 | |||
277 | QDateTime Event::end( bool actual ) const | ||
278 | { | ||
279 | QDateTime dt = (endUTC > 0) ? TimeConversion::fromUTC( endUTC ) : QDateTime::currentDateTime(); | ||
280 | |||
281 | if ( actual && typ == AllDay ) { | ||
282 | QTime t = dt.time(); | ||
283 | t.setHMS( 23, 59, 59 ); | ||
284 | dt.setTime( t ); | ||
285 | } | ||
286 | return dt; | ||
287 | } | ||
288 | |||
289 | const QString &Event::timeZone() const | ||
290 | { | ||
291 | return tz; | ||
292 | } | ||
293 | |||
294 | bool Event::hasAlarm() const | ||
295 | { | ||
296 | return hAlarm; | ||
297 | } | ||
298 | |||
299 | int Event::alarmTime() const | ||
300 | { | ||
301 | return aMinutes; | ||
302 | } | ||
303 | |||
304 | Event::SoundTypeChoice Event::alarmSound() const | ||
305 | { | ||
306 | return aSound; | ||
307 | } | ||
308 | |||
309 | bool Event::hasRepeat() const | ||
310 | { | ||
311 | return doRepeat(); | ||
312 | } | ||
313 | |||
314 | const Event::RepeatPattern &Event::repeatPattern() const | ||
315 | { | ||
316 | return pattern; | ||
317 | } | ||
318 | |||
319 | Event::RepeatPattern &Event::repeatPattern() | ||
320 | { | ||
321 | return pattern; | ||
322 | } | ||
323 | |||
324 | const QString &Event::notes() const | ||
325 | { | ||
326 | return note; | ||
327 | } | ||
328 | |||
329 | bool Event::operator==( const Event &e ) const | ||
330 | { | ||
331 | return ( e.descript == descript && | ||
332 | e.locat == locat && | ||
333 | e.categ == categ && | ||
334 | e.typ == typ && | ||
335 | e.startUTC == startUTC && | ||
336 | e.endUTC == endUTC && | ||
337 | e.tz == tz && | ||
338 | e.hAlarm == hAlarm && | ||
339 | e.aMinutes == aMinutes && | ||
340 | e.aSound == aSound && | ||
341 | e.hRepeat == hRepeat && | ||
342 | e.pattern == pattern && | ||
343 | e.note == note ); | ||
344 | } | ||
345 | |||
346 | void Event::save( QString& buf ) | ||
347 | { | ||
348 | buf += " description=\"" + Qtopia::escapeString(descript) + "\""; | ||
349 | if ( !locat.isEmpty() ) | ||
350 | buf += " location=\"" + Qtopia::escapeString(locat) + "\""; | ||
351 | // save the categoies differently.... | ||
352 | QString strCats = idsToString( categories() ); | ||
353 | buf += " categories=\"" + Qtopia::escapeString(strCats) + "\""; | ||
354 | buf += " uid=\"" + QString::number( uid() ) + "\""; | ||
355 | if ( (Type)typ != Normal ) | ||
356 | buf += " type=\"AllDay\""; | ||
357 | if ( hAlarm ) { | ||
358 | buf += " alarm=\"" + QString::number( aMinutes ) + "\" sound=\""; | ||
359 | if ( aSound == Event::Loud ) | ||
360 | buf += "loud"; | ||
361 | else | ||
362 | buf += "silent"; | ||
363 | buf += "\""; | ||
364 | } | ||
365 | if ( hRepeat ) | ||
366 | write( buf, pattern ); | ||
367 | |||
368 | buf += " start=\"" | ||
369 | + QString::number( startUTC ) | ||
370 | + "\""; | ||
371 | |||
372 | buf += " end=\"" | ||
373 | + QString::number( endUTC ) | ||
374 | + "\""; | ||
375 | |||
376 | if ( !note.isEmpty() ) | ||
377 | buf += " note=\"" + Qtopia::escapeString( note ) + "\""; | ||
378 | buf += customToXml(); | ||
379 | } | ||
380 | |||
381 | bool Event::RepeatPattern::operator==( const Event::RepeatPattern &right ) const | ||
382 | { | ||
383 | // *sigh* | ||
384 | return ( type == right.type | ||
385 | && frequency == right.frequency | ||
386 | && position == right.position | ||
387 | && days == right.days | ||
388 | && hasEndDate == right.hasEndDate | ||
389 | && endDateUTC == right.endDateUTC | ||
390 | && createTime == right.createTime ); | ||
391 | } | ||
392 | |||
393 | |||
394 | class EffectiveEventPrivate | ||
395 | { | ||
396 | public: | ||
397 | //currently the existence of the d pointer means multi-day repeating, | ||
398 | //msut be changed if we use the d pointer for anything else. | ||
399 | QDate startDate; | ||
400 | QDate endDate; | ||
401 | }; | ||
402 | |||
403 | |||
404 | EffectiveEvent::EffectiveEvent() | ||
405 | { | ||
406 | mDate = QDate::currentDate(); | ||
407 | mStart = mEnd = QTime::currentTime(); | ||
408 | d = 0; | ||
409 | } | ||
410 | |||
411 | EffectiveEvent::EffectiveEvent( const Event &e, const QDate &date, Position pos ) | ||
412 | { | ||
413 | mEvent = e; | ||
414 | mDate = date; | ||
415 | if ( pos & Start ) | ||
416 | mStart = e.start( TRUE ).time(); | ||
417 | else | ||
418 | mStart = QTime( 0, 0, 0 ); | ||
419 | |||
420 | if ( pos & End ) | ||
421 | mEnd = e.end( TRUE ).time(); | ||
422 | else | ||
423 | mEnd = QTime( 23, 59, 59 ); | ||
424 | d = 0; | ||
425 | } | ||
426 | |||
427 | EffectiveEvent::~EffectiveEvent() | ||
428 | { | ||
429 | delete d; | ||
430 | } | ||
431 | |||
432 | EffectiveEvent::EffectiveEvent( const EffectiveEvent &e ) | ||
433 | { | ||
434 | d = 0; | ||
435 | *this = e; | ||
436 | } | ||
437 | |||
438 | EffectiveEvent& EffectiveEvent::operator=( const EffectiveEvent & e ) | ||
439 | { | ||
440 | if ( &e == this ) | ||
441 | return *this; | ||
442 | delete d; | ||
443 | if ( e.d ) { | ||
444 | d = new EffectiveEventPrivate; | ||
445 | d->startDate = e.d->startDate; | ||
446 | d->endDate = e.d->endDate; | ||
447 | } else { | ||
448 | d = 0; | ||
449 | } | ||
450 | mEvent = e.mEvent; | ||
451 | mDate = e.mDate; | ||
452 | mStart = e.mStart; | ||
453 | mEnd = e.mEnd; | ||
454 | |||
455 | return *this; | ||
456 | |||
457 | } | ||
458 | |||
459 | // QString EffectiveEvent::category() const | ||
460 | // { | ||
461 | // return mEvent.category(); | ||
462 | // } | ||
463 | |||
464 | const QString &EffectiveEvent::description( ) const | ||
465 | { | ||
466 | return mEvent.description(); | ||
467 | } | ||
468 | |||
469 | const QString &EffectiveEvent::location( ) const | ||
470 | { | ||
471 | return mEvent.location(); | ||
472 | } | ||
473 | |||
474 | const QString &EffectiveEvent::notes() const | ||
475 | { | ||
476 | return mEvent.notes(); | ||
477 | } | ||
478 | |||
479 | const Event &EffectiveEvent::event() const | ||
480 | { | ||
481 | return mEvent; | ||
482 | } | ||
483 | |||
484 | const QTime &EffectiveEvent::end() const | ||
485 | { | ||
486 | return mEnd; | ||
487 | } | ||
488 | |||
489 | const QTime &EffectiveEvent::start() const | ||
490 | { | ||
491 | return mStart; | ||
492 | } | ||
493 | |||
494 | const QDate &EffectiveEvent::date() const | ||
495 | { | ||
496 | return mDate; | ||
497 | } | ||
498 | |||
499 | int EffectiveEvent::length() const | ||
500 | { | ||
501 | return (mEnd.hour() * 60 - mStart.hour() * 60) | ||
502 | + QABS(mStart.minute() - mEnd.minute() ); | ||
503 | } | ||
504 | |||
505 | void EffectiveEvent::setDate( const QDate &dt ) | ||
506 | { | ||
507 | mDate = dt; | ||
508 | } | ||
509 | |||
510 | void EffectiveEvent::setStart( const QTime &start ) | ||
511 | { | ||
512 | mStart = start; | ||
513 | } | ||
514 | |||
515 | void EffectiveEvent::setEnd( const QTime &end ) | ||
516 | { | ||
517 | mEnd = end; | ||
518 | } | ||
519 | |||
520 | void EffectiveEvent::setEvent( Event e ) | ||
521 | { | ||
522 | mEvent = e; | ||
523 | } | ||
524 | |||
525 | bool EffectiveEvent::operator<( const EffectiveEvent &e ) const | ||
526 | { | ||
527 | if ( mDate < e.date() ) | ||
528 | return TRUE; | ||
529 | if ( mDate == e.date() ) | ||
530 | return ( mStart < e.start() ); | ||
531 | else | ||
532 | return FALSE; | ||
533 | } | ||
534 | |||
535 | bool EffectiveEvent::operator<=( const EffectiveEvent &e ) const | ||
536 | { | ||
537 | return (mDate <= e.date() ); | ||
538 | } | ||
539 | |||
540 | bool EffectiveEvent::operator==( const EffectiveEvent &e ) const | ||
541 | { | ||
542 | return ( mDate == e.date() | ||
543 | && mStart == e.start() | ||
544 | && mEnd == e.end() | ||
545 | && mEvent == e.event() ); | ||
546 | } | ||
547 | |||
548 | bool EffectiveEvent::operator!=( const EffectiveEvent &e ) const | ||
549 | { | ||
550 | return !(*this == e); | ||
551 | } | ||
552 | |||
553 | bool EffectiveEvent::operator>( const EffectiveEvent &e ) const | ||
554 | { | ||
555 | return !(*this <= e ); | ||
556 | } | ||
557 | |||
558 | bool EffectiveEvent::operator>=(const EffectiveEvent &e) const | ||
559 | { | ||
560 | return !(*this < e); | ||
561 | } | ||
562 | |||
563 | void EffectiveEvent::setEffectiveDates( const QDate &from, const QDate &to ) | ||
564 | { | ||
565 | if ( !from.isValid() ) { | ||
566 | delete d; | ||
567 | d = 0; | ||
568 | return; | ||
569 | } | ||
570 | if ( !d ) | ||
571 | d = new EffectiveEventPrivate; | ||
572 | d->startDate = from; | ||
573 | d->endDate = to; | ||
574 | } | ||
575 | |||
576 | QDate EffectiveEvent::startDate() const | ||
577 | { | ||
578 | if ( d ) | ||
579 | return d->startDate; | ||
580 | else if ( mEvent.hasRepeat() ) | ||
581 | return mDate; // single day, since multi-day should have a d pointer | ||
582 | else | ||
583 | return mEvent.start().date(); | ||
584 | } | ||
585 | |||
586 | QDate EffectiveEvent::endDate() const | ||
587 | { | ||
588 | if ( d ) | ||
589 | return d->endDate; | ||
590 | else if ( mEvent.hasRepeat() ) | ||
591 | return mDate; // single day, since multi-day should have a d pointer | ||
592 | else | ||
593 | return mEvent.end().date(); | ||
594 | } | ||
595 | |||
596 | int EffectiveEvent::size() const | ||
597 | { | ||
598 | return ( mEnd.hour() - mStart.hour() ) * 3600 | ||
599 | + (mEnd.minute() - mStart.minute() * 60 | ||
600 | + mEnd.second() - mStart.second() ); | ||
601 | } | ||
602 | |||
603 | |||
604 | // vcal conversion code | ||
605 | static inline VObject *safeAddPropValue( VObject *o, const char *prop, const QString &value ) | ||
606 | { | ||
607 | VObject *ret = 0; | ||
608 | if ( o && !value.isEmpty() ) | ||
609 | ret = addPropValue( o, prop, value.latin1() ); | ||
610 | return ret; | ||
611 | } | ||
612 | |||
613 | static inline VObject *safeAddProp( VObject *o, const char *prop) | ||
614 | { | ||
615 | VObject *ret = 0; | ||
616 | if ( o ) | ||
617 | ret = addProp( o, prop ); | ||
618 | return ret; | ||
619 | } | ||
620 | |||
621 | static VObject *createVObject( const Event &e ) | ||
622 | { | ||
623 | VObject *vcal = newVObject( VCCalProp ); | ||
624 | safeAddPropValue( vcal, VCVersionProp, "1.0" ); | ||
625 | VObject *event = safeAddProp( vcal, VCEventProp ); | ||
626 | |||
627 | safeAddPropValue( event, VCDTstartProp, TimeConversion::toISO8601( e.start() ) ); | ||
628 | safeAddPropValue( event, VCDTendProp, TimeConversion::toISO8601( e.end() ) ); | ||
629 | safeAddPropValue( event, "X-Qtopia-NOTES", e.description() ); | ||
630 | safeAddPropValue( event, VCDescriptionProp, e.description() ); | ||
631 | safeAddPropValue( event, VCLocationProp, e.location() ); | ||
632 | |||
633 | if ( e.hasAlarm() ) { | ||
634 | VObject *alarm = safeAddProp( event, VCAAlarmProp ); | ||
635 | QDateTime dt = e.start(); | ||
636 | dt = dt.addSecs( -e.alarmTime()*60 ); | ||
637 | safeAddPropValue( alarm, VCRunTimeProp, TimeConversion::toISO8601( dt ) ); | ||
638 | safeAddPropValue( alarm, VCAudioContentProp, | ||
639 | (e.alarmSound() == Event::Silent ? "silent" : "alarm" ) ); | ||
640 | } | ||
641 | |||
642 | safeAddPropValue( event, "X-Qtopia-TIMEZONE", e.timeZone() ); | ||
643 | |||
644 | if ( e.type() == Event::AllDay ) | ||
645 | safeAddPropValue( event, "X-Qtopia-AllDay", e.timeZone() ); | ||
646 | |||
647 | // ### repeat missing | ||
648 | |||
649 | // ### categories missing | ||
650 | |||
651 | return vcal; | ||
652 | } | ||
653 | |||
654 | |||
655 | static Event parseVObject( VObject *obj ) | ||
656 | { | ||
657 | Event e; | ||
658 | |||
659 | bool haveAlarm = FALSE; | ||
660 | bool haveStart = FALSE; | ||
661 | bool haveEnd = FALSE; | ||
662 | QDateTime alarmTime; | ||
663 | Event::SoundTypeChoice soundType = Event::Silent; | ||
664 | |||
665 | VObjectIterator it; | ||
666 | initPropIterator( &it, obj ); | ||
667 | while( moreIteration( &it ) ) { | ||
668 | VObject *o = nextVObject( &it ); | ||
669 | QCString name = vObjectName( o ); | ||
670 | QCString value = vObjectStringZValue( o ); | ||
671 | if ( name == VCDTstartProp ) { | ||
672 | e.setStart( TimeConversion::fromISO8601( value ) ); | ||
673 | haveStart = TRUE; | ||
674 | } | ||
675 | else if ( name == VCDTendProp ) { | ||
676 | e.setEnd( TimeConversion::fromISO8601( value ) ); | ||
677 | haveEnd = TRUE; | ||
678 | } | ||
679 | else if ( name == "X-Qtopia-NOTES" ) { | ||
680 | e.setNotes( value ); | ||
681 | } | ||
682 | else if ( name == VCDescriptionProp ) { | ||
683 | e.setDescription( value ); | ||
684 | } | ||
685 | else if ( name == VCLocationProp ) { | ||
686 | e.setLocation( value ); | ||
687 | } | ||
688 | else if ( name == VCAudioContentProp ) { | ||
689 | haveAlarm = TRUE; | ||
690 | VObjectIterator nit; | ||
691 | initPropIterator( &nit, o ); | ||
692 | while( moreIteration( &nit ) ) { | ||
693 | VObject *o = nextVObject( &nit ); | ||
694 | QCString name = vObjectName( o ); | ||
695 | QCString value = vObjectStringZValue( o ); | ||
696 | if ( name == VCRunTimeProp ) | ||
697 | alarmTime = TimeConversion::fromISO8601( value ); | ||
698 | else if ( name == VCAudioContentProp ) { | ||
699 | if ( value == "silent" ) | ||
700 | soundType = Event::Silent; | ||
701 | else | ||
702 | soundType = Event::Loud; | ||
703 | } | ||
704 | } | ||
705 | } | ||
706 | else if ( name == "X-Qtopia-TIMEZONE") { | ||
707 | e.setTimeZone( value ); | ||
708 | } | ||
709 | else if ( name == "X-Qtopia-AllDay" ) { | ||
710 | e.setType( Event::AllDay ); | ||
711 | } | ||
712 | #if 0 | ||
713 | else { | ||
714 | printf("Name: %s, value=%s\n", name.data(), vObjectStringZValue( o ) ); | ||
715 | VObjectIterator nit; | ||
716 | initPropIterator( &nit, o ); | ||
717 | while( moreIteration( &nit ) ) { | ||
718 | VObject *o = nextVObject( &nit ); | ||
719 | QCString name = vObjectName( o ); | ||
720 | QString value = vObjectStringZValue( o ); | ||
721 | printf(" subprop: %s = %s\n", name.data(), value.latin1() ); | ||
722 | } | ||
723 | } | ||
724 | #endif | ||
725 | } | ||
726 | |||
727 | if ( !haveStart && !haveEnd ) | ||
728 | e.setStart( QDateTime::currentDateTime() ); | ||
729 | |||
730 | if ( !haveEnd ) { | ||
731 | e.setType( Event::AllDay ); | ||
732 | e.setEnd( e.start() ); | ||
733 | } | ||
734 | |||
735 | if ( haveAlarm ) { | ||
736 | int minutes = alarmTime.secsTo( e.start() ) / 60; | ||
737 | e.setAlarm( TRUE, minutes, soundType ); | ||
738 | } | ||
739 | return e; | ||
740 | } | ||
741 | |||
742 | |||
743 | |||
744 | void Event::writeVCalendar( const QString &filename, const QValueList<Event> &events) | ||
745 | { | ||
746 | QFileDirect f( filename.utf8().data() ); | ||
747 | if ( !f.open( IO_WriteOnly ) ) { | ||
748 | qWarning("Unable to open vcard write"); | ||
749 | return; | ||
750 | } | ||
751 | |||
752 | QValueList<Event>::ConstIterator it; | ||
753 | for( it = events.begin(); it != events.end(); ++it ) { | ||
754 | VObject *obj = createVObject( *it ); | ||
755 | writeVObject( f.directHandle() , obj ); | ||
756 | cleanVObject( obj ); | ||
757 | } | ||
758 | |||
759 | cleanStrTbl(); | ||
760 | } | ||
761 | |||
762 | void Event::writeVCalendar( const QString &filename, const Event &event) | ||
763 | { | ||
764 | QFileDirect f( filename.utf8().data() ); | ||
765 | if ( !f.open( IO_WriteOnly ) ) { | ||
766 | qWarning("Unable to open vcard write"); | ||
767 | return; | ||
768 | } | ||
769 | |||
770 | VObject *obj = createVObject( event ); | ||
771 | writeVObject( f.directHandle() , obj ); | ||
772 | cleanVObject( obj ); | ||
773 | |||
774 | cleanStrTbl(); | ||
775 | } | ||
776 | |||
777 | |||
778 | QValueList<Event> Event::readVCalendar( const QString &filename ) | ||
779 | { | ||
780 | VObject *obj = Parse_MIME_FromFileName( (char *)filename.utf8().data() ); | ||
781 | |||
782 | QValueList<Event> events; | ||
783 | |||
784 | while ( obj ) { | ||
785 | QCString name = vObjectName( obj ); | ||
786 | if ( name == VCCalProp ) { | ||
787 | VObjectIterator nit; | ||
788 | initPropIterator( &nit, obj ); | ||
789 | while( moreIteration( &nit ) ) { | ||
790 | VObject *o = nextVObject( &nit ); | ||
791 | QCString name = vObjectName( o ); | ||
792 | if ( name == VCEventProp ) | ||
793 | events.append( parseVObject( o ) ); | ||
794 | } | ||
795 | } else if ( name == VCEventProp ) { | ||
796 | // shouldn't happen, but just to be sure | ||
797 | events.append( parseVObject( obj ) ); | ||
798 | } | ||
799 | VObject *t = obj; | ||
800 | obj = nextVObjectInList(obj); | ||
801 | cleanVObject( t ); | ||
802 | } | ||
803 | |||
804 | return events; | ||
805 | } | ||
806 | |||
807 | bool Event::match( const QRegExp &r ) const | ||
808 | { | ||
809 | bool returnMe; | ||
810 | returnMe = false; | ||
811 | |||
812 | if ( descript.find( r ) > -1 ) | ||
813 | returnMe = true; | ||
814 | else if ( locat.find( r ) > -1 ) | ||
815 | returnMe = true; | ||
816 | else if ( TimeConversion::fromUTC( startUTC ).toString().find( r ) > -1 ) | ||
817 | returnMe = true; | ||
818 | else if ( TimeConversion::fromUTC( endUTC ).toString().find( r ) > -1 ) | ||
819 | returnMe = true; | ||
820 | else if ( tz.find( r ) > -1 ) | ||
821 | returnMe = true; | ||
822 | else if ( note.find( r ) > -1 ) | ||
823 | returnMe = true; | ||
824 | else if ( doRepeat() ) { | ||
825 | if ( pattern.hasEndDate ) | ||
826 | if ( TimeConversion::fromUTC( pattern.endDateUTC ).toString().find(r) > -1 ) | ||
827 | returnMe = true; | ||
828 | } | ||
829 | return returnMe; | ||
830 | } | ||