1/*
2 This file is part of the kcalcore library.
3
4 Copyright (c) 2005-2007 David Jarvie <djarvie@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20*/
21#ifndef KCALCORE_ICALTIMEZONES_H
22#define KCALCORE_ICALTIMEZONES_H
23
24#include "kcalcore_export.h"
25
26#include <KDE/KTimeZone>
27
28#include <QtCore/QMap>
29
30#ifndef ICALCOMPONENT_H
31typedef struct icalcomponent_impl icalcomponent;
32#endif
33#ifndef ICALTIMEZONE_DEFINED
34#define ICALTIMEZONE_DEFINED
35typedef struct _icaltimezone icaltimezone;
36#endif
37
38namespace KCalCore {
39
40class ICalTimeZone;
41class ICalTimeZoneSource;
42class ICalTimeZoneData;
43class ICalTimeZonesPrivate;
44class ICalTimeZonePrivate;
45class ICalTimeZoneSourcePrivate;
46class ICalTimeZoneDataPrivate;
47
48/**
49 * The ICalTimeZones class represents a time zone database which consists of a
50 * collection of individual iCalendar time zone definitions.
51 *
52 * Each individual time zone is defined in a ICalTimeZone instance. The time zones in the
53 * collection are indexed by name, which must be unique within the collection.
54 *
55 * Different calendars could define the same time zone differently. As a result,
56 * to avoid conflicting definitions, each calendar should normally have its own
57 * ICalTimeZones collection.
58 *
59 * This class is analogous to KTimeZones, but holds ICalTimeZone instances
60 * rather than generic KTimeZone instances.
61 *
62 * @short Represents a collection of iCalendar time zones
63 * @author David Jarvie <djarvie@kde.org>
64 */
65class KCALCORE_EXPORT ICalTimeZones
66{
67public:
68 /**
69 * Constructs an empty time zone collection.
70 */
71 ICalTimeZones();
72
73 /**
74 * Copy constructor.
75 * @param rhs is the ICalTimeZones instance to copy.
76 */
77 ICalTimeZones(const ICalTimeZones &rhs);
78
79 /**
80 * Assignment operator.
81 * @param rhs is the ICalTimeZones instance to assign to this one.
82 */
83 ICalTimeZones &operator=(const ICalTimeZones &rhs);
84
85 /**
86 * Destructor.
87 */
88 ~ICalTimeZones();
89
90 /**
91 * Returns the time zone with the given name.
92 * Note that the ICalTimeZone returned remains a member of the ICalTimeZones
93 * collection, and should not be deleted without calling remove() first.
94 *
95 * @param name name of time zone
96 * @return time zone, or invalid if not found
97 */
98 ICalTimeZone zone(const QString &name) const;
99
100 /**
101 * Returns the time zone with similar zone information regardless of
102 * the time zone names. This feature was added for Microsoft ActiveSync
103 * which may have the same timezone specification separately for every
104 * incidence.
105 * Note that the ICalTimeZone returned remains a member of the ICalTimeZones
106 * collection, and should not be deleted without calling remove() first.
107 *
108 * @see ICalTimeZone parse( MSTimeZone *tz, ICalTimeZones &zones );
109 * @param zone zone information to look for
110 * @return time zone, or invalid if not found
111 */
112 ICalTimeZone zone(const ICalTimeZone &zone) const;
113
114 typedef QMap<QString, ICalTimeZone> ZoneMap;
115
116 /**
117 * Returns all the time zones defined in this collection.
118 *
119 * @return time zone collection
120 */
121 const ZoneMap zones() const;
122
123 /**
124 * Adds a time zone to the collection.
125 * The time zone's name must be unique within the collection.
126 *
127 * @param zone time zone to add
128 * @return @c true if successful, @c false if zone's name duplicates one
129 * already in the collection
130 */
131 bool add(const ICalTimeZone &zone);
132
133 /**
134 * Removes a time zone from the collection.
135 *
136 * @param zone time zone to remove
137 * @return the time zone which was removed, or invalid if not found
138 */
139 ICalTimeZone remove(const ICalTimeZone &zone);
140
141 /**
142 * Removes a time zone from the collection.
143 *
144 * @param name name of time zone to remove
145 * @return the time zone which was removed, or invalid if not found
146 */
147 ICalTimeZone remove(const QString &name);
148
149 /**
150 * Clears the collection.
151 */
152 void clear();
153
154 /**
155 * Returns the number of zones kept in memory.
156 *
157 * @return The number of zones
158 */
159 int count();
160
161private:
162 //@cond PRIVATE
163 ICalTimeZonesPrivate *const d;
164 //@endcond
165};
166
167/**
168 * The ICalTimeZone class represents an iCalendar VTIMEZONE component.
169 *
170 * ICalTimeZone instances are normally created by ICalTimeZoneSource::parse().
171 *
172 * @short An iCalendar time zone
173 * @see ICalTimeZoneSource, ICalTimeZoneData
174 * @author David Jarvie <djarvie@kde.org>
175 */
176class KCALCORE_EXPORT ICalTimeZone : public KTimeZone //krazy:exclude=dpointer
177 //(no d-pointer for KTimeZone derived classes)
178{
179public:
180 /**
181 * Constructs a null time zone. A null time zone is invalid.
182 *
183 * @see isValid()
184 */
185 ICalTimeZone();
186
187 /**
188 * Creates a time zone. This constructor is normally called from
189 * ICalTimeZoneSource::parse().
190 *
191 * @param source iCalendar VTIMEZONE reader and parser
192 * @param name time zone's unique name within the iCalendar object
193 * @param data parsed VTIMEZONE data
194 */
195 ICalTimeZone(ICalTimeZoneSource *source, const QString &name, ICalTimeZoneData *data);
196
197 /**
198 * Constructor which converts a KTimeZone to an ICalTimeZone instance.
199 *
200 * @param tz KTimeZone instance
201 * @param earliest earliest date for which time zone data should be stored
202 */
203 explicit ICalTimeZone(const KTimeZone &tz, const QDate &earliest = QDate());
204
205 /**
206 * Destructor.
207 */
208 virtual ~ICalTimeZone();
209
210 /**
211 * Returns the name of the city for this time zone, if any. There is no
212 * fixed format for the name.
213 *
214 * @return city name
215 */
216 QString city() const;
217
218 /**
219 * Returns the URL of the published VTIMEZONE definition, if any.
220 *
221 * @return URL
222 */
223 QByteArray url() const;
224
225 /**
226 * Returns the LAST-MODIFIED time of the VTIMEZONE, if any.
227 *
228 * @return time, or QDateTime() if none
229 */
230 QDateTime lastModified() const;
231
232 /**
233 * Returns the VTIMEZONE string which represents this time zone.
234 *
235 * @return VTIMEZONE string
236 */
237 QByteArray vtimezone() const;
238
239 /**
240 * Returns the ICal timezone structure which represents this time zone.
241 * The caller is responsible for freeing the returned structure using
242 * icaltimezone_free().
243 *
244 * @return icaltimezone structure
245 */
246 icaltimezone *icalTimezone() const;
247
248 /**
249 * Update the definition of the time zone to be identical to another
250 * ICalTimeZone instance. A prerequisite is that the two instances must
251 * have the same name.
252 *
253 * The purpose of this method is to enable updates of ICalTimeZone
254 * definitions when a calendar is reloaded, without invalidating pointers
255 * to the instance (particularly pointers held by KDateTime objects).
256 *
257 * @param other time zone whose definition is to be used
258 * @return true if definition was updated (i.e. names are the same)
259 */
260 bool update(const ICalTimeZone &other);
261
262 /**
263 * Returns a standard UTC time zone, with name "UTC".
264 *
265 * @note The ICalTimeZone returned by this method does not belong to any
266 * ICalTimeZones collection. Any ICalTimeZones instance may contain its own
267 * UTC ICalTimeZone defined by its time zone source data, but that will be
268 * a different instance than this ICalTimeZone.
269 *
270 * @return UTC time zone
271 */
272 static ICalTimeZone utc();
273
274protected:
275 /**
276 @copydoc
277 IncidenceBase::virtual_hook()
278 */
279 virtual void virtual_hook(int id, void *data);
280
281private:
282 // d-pointer is in ICalTimeZoneBackend.
283 // This is a requirement for classes inherited from KTimeZone.
284};
285
286/**
287 * Backend class for KICalTimeZone class.
288 *
289 * This class implements KICalTimeZone's constructors and virtual methods. A
290 * backend class is required for all classes inherited from KTimeZone to
291 * allow KTimeZone virtual methods to work together with reference counting of
292 * private data.
293 *
294 * @short Backend class for KICalTimeZone class
295 * @see KTimeZoneBackend, KICalTimeZone, KTimeZone
296 * @ingroup timezones
297 * @author David Jarvie <djarvie@kde.org>
298 */
299class KCALCORE_EXPORT ICalTimeZoneBackend : public KTimeZoneBackend
300{
301public:
302 /** Implements ICalTimeZone::ICalTimeZone(). */
303 ICalTimeZoneBackend();
304 /**
305 * Implements ICalTimeZone::ICalTimeZone().
306 *
307 * @param source iCalendar VTIMEZONE reader and parser
308 * @param name time zone's unique name within the iCalendar object
309 * @param countryCode ISO 3166 2-character country code, empty if unknown
310 * @param latitude in degrees (between -90 and +90), UNKNOWN if not known
311 * @param longitude in degrees (between -180 and +180), UNKNOWN if not known
312 * @param comment description of the time zone, if any
313 */
314 ICalTimeZoneBackend(ICalTimeZoneSource *source, const QString &name,
315 const QString &countryCode = QString(),
316 float latitude = KTimeZone::UNKNOWN,
317 float longitude = KTimeZone::UNKNOWN,
318 const QString &comment = QString());
319
320 /** Implements ICalTimeZone::ICalTimeZone().
321 *
322 * @param tz KTimeZone instance
323 * @param earliest earliest date for which time zone data should be stored
324 */
325 ICalTimeZoneBackend(const KTimeZone &tz, const QDate &earliest);
326
327 virtual ~ICalTimeZoneBackend();
328
329 /**
330 * Creates a copy of this instance.
331 *
332 * @return new copy
333 */
334 virtual KTimeZoneBackend *clone() const;
335
336 /**
337 * Returns the class name of the data represented by this instance.
338 *
339 * @return "ICalTimeZone"
340 */
341 virtual QByteArray type() const;
342
343 /**
344 * Implements ICalTimeZone::hasTransitions().
345 *
346 * Return whether daylight saving transitions are available for the time zone.
347 *
348 * @param caller calling ICalTimeZone object
349 * @return @c true
350 */
351 virtual bool hasTransitions(const KTimeZone *caller) const;
352
353protected:
354 /**
355 @copydoc
356 IncidenceBase::virtual_hook()
357 */
358 virtual void virtual_hook(int id, void *data);
359
360private:
361 //@cond PRIVATE
362 ICalTimeZonePrivate *d; //krazy:exclude=dpointer
363 //(non-const d-pointer for KTimeZoneBackend-derived classes)
364 //@endcond
365};
366
367/**
368 * Placeholhers for Microsoft and ActiveSync timezone data.
369 * @see http://msdn.microsoft.com/en-us/library/ms725481(VS.85).aspx
370 * (TIME_ZONE_INFORMATION Structure)
371 */
372
373typedef struct _MSSystemTime {
374 qint16 wYear;
375 qint16 wMonth;
376 qint16 wDayOfWeek;
377 qint16 wDay;
378 qint16 wHour;
379 qint16 wMinute;
380 qint16 wSecond;
381 qint16 wMilliseconds;
382} MSSystemTime;
383
384typedef struct _MSTimeZone {
385 long Bias;
386 QString StandardName;
387 MSSystemTime StandardDate;
388 long StandardBias;
389 QString DaylightName;
390 MSSystemTime DaylightDate;
391 long DaylightBias;
392} MSTimeZone;
393
394/**
395 * A class which reads and parses iCalendar VTIMEZONE components, and accesses
396 * libical time zone data.
397 *
398 * ICalTimeZoneSource is used to parse VTIMEZONE components and create
399 * ICalTimeZone instances to represent them.
400 *
401 * @short Reader and parser for iCalendar time zone data
402 * @see ICalTimeZone, ICalTimeZoneData
403 * @author David Jarvie <djarvie@kde.org>
404 */
405class KCALCORE_EXPORT ICalTimeZoneSource : public KTimeZoneSource
406{
407public:
408 /**
409 * Constructs an iCalendar time zone source.
410 */
411 ICalTimeZoneSource();
412
413 /**
414 * Destructor.
415 */
416 virtual ~ICalTimeZoneSource();
417
418 /**
419 * Creates an ICalTimeZone instance containing the detailed information
420 * parsed from an iCalendar VTIMEZONE component.
421 *
422 * @param vtimezone the VTIMEZONE component from which data is to be extracted
423 * @return an ICalTimeZone instance containing the parsed data, or invalid on error
424 */
425 ICalTimeZone parse(icalcomponent *vtimezone);
426
427 /**
428 * Creates an ICalTimeZone instance for each iCalendar VTIMEZONE component
429 * within a CALENDAR component. The ICalTimeZone instances are added to a
430 * ICalTimeZones collection.
431 *
432 * If an error occurs while processing any time zone, any remaining time
433 * zones are left unprocessed.
434 *
435 * @param calendar the CALENDAR component from which data is to be extracted
436 * @param zones the time zones collection to which the ICalTimeZone
437 * instances are to be added
438 * @return @c false if any error occurred (either parsing a VTIMEZONE
439 * component or adding an ICalTimeZone to @p zones), @c true otherwise
440 */
441 bool parse(icalcomponent *calendar, ICalTimeZones &zones);
442
443 /**
444 * Creates an ICalTimeZone instance containing the detailed information
445 * contained in an MSTimeZone structure.
446 *
447 * @param tz the MSTimeZone structure from which data is to be extracted
448 * @return an ICalTimeZone instance containing the time zone data, or invalid on error
449 */
450 ICalTimeZone parse(MSTimeZone *tz);
451
452 /**
453 * Creates an ICalTimeZone instance and adds it to a ICalTimeZones
454 * collection or returns an existing instance for the MSTimeZone component.
455 *
456 * @param tz the MSTimeZone structure to parse
457 * @param zones the time zones collection to which the ICalTimeZone
458 * instances are to be added
459 * @return an ICalTimeZone instance containing the time zone data, or invalid on error
460 */
461 ICalTimeZone parse(MSTimeZone *tz, ICalTimeZones &zones);
462
463 /**
464 * Creates an ICalTimeZone instance containing the detailed information
465 * contained in a QStringList produced by vcalformat, and adds it to a
466 * ICalTimeZones collection or returns an existing instance for the vcal
467 * component.
468 *
469 * @param name the name of timezone
470 * @param tzList the QStringList to parse
471 * @param zones the time zones collection to which the ICalTimeZone
472 * instances are to be added
473 * @return an ICalTimeZone instance containing the time zone data, or invalid on error
474 */
475 ICalTimeZone parse(const QString &name, const QStringList &tzList, ICalTimeZones &zones);
476
477 /**
478 * Creates an ICalTimeZone instance containing the detailed information
479 * contained in a QStringList produced by vcalformat.
480 *
481 * @param name the name of timezone
482 * @param tzList the QStringList from which data is to be extracted
483 * @return an ICalTimeZone instance containing the time zone data, or invalid on error
484 */
485 ICalTimeZone parse(const QString &name, const QStringList &tzList);
486
487 /**
488 * Reads an iCalendar file and creates an ICalTimeZone instance for each
489 * VTIMEZONE component within it. The ICalTimeZone instances are added to a
490 * ICalTimeZones collection.
491 *
492 * If an error occurs while processing any time zone, any remaining time
493 * zones are left unprocessed.
494 *
495 * @param fileName the file from which data is to be extracted
496 * @param zones the time zones collection to which the ICalTimeZone
497 * instances are to be added
498 * @return @c false if any error occurred, @c true otherwise
499 */
500 bool parse(const QString &fileName, ICalTimeZones &zones);
501
502 /**
503 * Creates an ICalTimeZone instance containing the detailed information
504 * contained in an icaltimezone structure.
505 *
506 * Note that an icaltimezone instance may internally refer to a built-in
507 * (i.e. system) time zone, in which case the data obtained from @p tz will
508 * actually be derived from the built-in time zone rather than from a
509 * VTIMEZONE component.
510 *
511 * @param tz the icaltimezone structure from which data is to be extracted
512 * @return an ICalTimeZone instance containing the time zone data, or invalid on error
513 */
514 ICalTimeZone parse(icaltimezone *tz);
515
516 /**
517 * Creates an ICalTimeZone instance for a standard time zone. The system
518 * time zone definition is used in preference; otherwise, the built-in
519 * libical time zone definition is used.
520 *
521 * @param zone time zone name, which may optionally include the libical
522 * prefix string
523 * @param icalBuiltIn @p true to fetch only the libical built-in time zone,
524 * and ignore system time zone definitions
525 * @return an ICalTimeZone instance containing the time zone data, or invalid on error
526 */
527 ICalTimeZone standardZone(const QString &zone, bool icalBuiltIn = false);
528
529 /**
530 * Returns the prefix string used in the TZID field in built-in libical
531 * time zones. The prefix string starts and ends with '/'. The name
532 * normally used for the time zone is obtained by stripping the prefix and
533 * the following characters up to the next '/', inclusive.
534 *
535 * @return prefix string
536 */
537 static QByteArray icalTzidPrefix();
538
539 using KTimeZoneSource::parse; // prevent warning about hidden virtual method
540
541protected:
542 /**
543 @copydoc
544 IncidenceBase::virtual_hook()
545 */
546 virtual void virtual_hook(int id, void *data);
547
548private:
549 //@cond PRIVATE
550 ICalTimeZoneSourcePrivate *const d;
551 //@endcond
552};
553
554/**
555 * Parsed iCalendar VTIMEZONE data.
556 *
557 * This class is used by the ICalTimeZoneSource class to pass parsed
558 * data to an ICalTimeZone intance.
559 *
560 * @short Parsed iCalendar time zone data
561 * @see ICalTimeZone, ICalTimeZoneSource
562 * @author David Jarvie <djarvie@kde.org>
563 */
564class KCALCORE_EXPORT ICalTimeZoneData : public KTimeZoneData
565{
566 friend class ICalTimeZoneSource;
567
568public:
569 /**
570 * Default constructor.
571 */
572 ICalTimeZoneData();
573
574 /**
575 * Copy constructor.
576 *
577 * @param rhs instance to copy from
578 */
579 ICalTimeZoneData(const ICalTimeZoneData &rhs);
580
581 /**
582 * Constructor which converts a KTimeZoneData to an ICalTimeZoneData instance.
583 * If @p data is for a system time zone (i.e. @p tz is a KSystemTimeZone
584 * instance), the full time zone data is read from the system time zone
585 * database if possible; otherwise, the built-in libical time zone's data
586 * is used.
587 *
588 * @param rhs KTimeZoneData instance
589 * @param tz time zone which @p rhs belongs to
590 * @param earliest earliest date for which time zone data should be stored
591 */
592 ICalTimeZoneData(const KTimeZoneData &rhs, const KTimeZone &tz, const QDate &earliest);
593
594 /**
595 * Destructor.
596 */
597 virtual ~ICalTimeZoneData();
598
599 /**
600 * Assignment operator.
601 *
602 * @param rhs instance to copy from
603 * @return this instance
604 */
605 ICalTimeZoneData &operator=(const ICalTimeZoneData &rhs);
606
607 /**
608 * Creates a new copy of this object.
609 * The caller is responsible for deleting the copy.
610 *
611 * @return copy of this instance
612 */
613 virtual KTimeZoneData *clone() const;
614
615 /**
616 * Returns the name of the city for this time zone, if any. There is no fixed
617 * format for the name.
618 *
619 * @return city name
620 */
621 QString city() const;
622
623 /**
624 * Returns the URL of the published VTIMEZONE definition, if any.
625 *
626 * @return URL
627 */
628 QByteArray url() const;
629
630 /**
631 * Returns the LAST-MODIFIED time of the VTIMEZONE, if any.
632 *
633 * @return time, or QDateTime() if none
634 */
635 QDateTime lastModified() const;
636
637 /**
638 * Returns the VTIMEZONE string which represents this time zone.
639 *
640 * @return VTIMEZONE string
641 */
642 QByteArray vtimezone() const;
643
644 /**
645 * Returns the ICal timezone structure which represents this time zone.
646 * The caller is responsible for freeing the returned structure using
647 * icaltimezone_free().
648 *
649 * @return icaltimezone structure
650 */
651 icaltimezone *icalTimezone() const;
652
653 /**
654 * Return whether daylight saving transitions are available for the time zone.
655 *
656 * @return @c true
657 */
658 virtual bool hasTransitions() const;
659
660protected:
661 /**
662 @copydoc
663 IncidenceBase::virtual_hook()
664 */
665 virtual void virtual_hook(int id, void *data);
666
667private:
668 //@cond PRIVATE
669 ICalTimeZoneDataPrivate *const d;
670 //@endcond
671};
672
673}
674
675#endif
676