• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.14.10 API Reference
  • KDE Home
  • Contact Us
 

KAlarm Library

  • kalarmcal
kacalendar.cpp
1/*
2 * kacalendar.cpp - KAlarm kcal library calendar and event functions
3 * This file is part of kalarmcal library, which provides access to KAlarm
4 * calendar data.
5 * Copyright © 2001-2013 by David Jarvie <djarvie@kde.org>
6 *
7 * This library is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Library General Public License as published
9 * by the Free Software Foundation; either version 2 of the License, or (at
10 * your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to the
19 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
21 */
22
23#include "kacalendar.h"
24
25#include "kaevent.h"
26#include "version.h"
27
28#ifndef KALARMCAL_USE_KRESOURCES
29#include "collectionattribute.h"
30
31#include <kcalcore/event.h>
32#include <kcalcore/alarm.h>
33#include <kcalcore/memorycalendar.h>
34
35#include <kmessagebox.h>
36#else
37#include <kcal/event.h>
38#include <kcal/alarm.h>
39#include <kcal/calendarlocal.h>
40#endif
41
42#include <kglobal.h>
43#include <klocalizedstring.h>
44#include <kdebug.h>
45
46#include <QMap>
47#include <QFile>
48#include <QFileInfo>
49#include <QTextStream>
50
51#ifndef KALARMCAL_USE_KRESOURCES
52using namespace KCalCore;
53using Akonadi::Collection;
54#else
55using namespace KCal;
56#endif
57
58static const KCatalogLoader loader(QLatin1String("libkalarmcal"));
59
60namespace KAlarmCal
61{
62
63#ifndef KALARMCAL_USE_KRESOURCES
64const QLatin1String MIME_BASE("application/x-vnd.kde.alarm");
65const QLatin1String MIME_ACTIVE("application/x-vnd.kde.alarm.active");
66const QLatin1String MIME_ARCHIVED("application/x-vnd.kde.alarm.archived");
67const QLatin1String MIME_TEMPLATE("application/x-vnd.kde.alarm.template");
68#endif
69
70static const QByteArray VERSION_PROPERTY("VERSION"); // X-KDE-KALARM-VERSION VCALENDAR property
71
72static bool isUTC(const QString& localFile);
73
74class Private
75{
76 public:
77#ifndef KALARMCAL_USE_KRESOURCES
78 static int readKAlarmVersion(const FileStorage::Ptr&, QString& subVersion, QString& versionString);
79#else
80 static int readKAlarmVersion(CalendarLocal&, const QString& localFile, QString& subVersion, QString& versionString);
81#endif
82
83 static QByteArray mIcalProductId;
84};
85
86QByteArray Private::mIcalProductId;
87
88//=============================================================================
89
90namespace KACalendar
91{
92
93const QByteArray APPNAME("KALARM");
94
95void setProductId(const QByteArray& progName, const QByteArray& progVersion)
96{
97 Private::mIcalProductId = QByteArray("-//K Desktop Environment//NONSGML " + progName + " " + progVersion + "//EN");
98}
99
100QByteArray icalProductId()
101{
102 return Private::mIcalProductId.isEmpty() ? QByteArray("-//K Desktop Environment//NONSGML //EN") : Private::mIcalProductId;
103}
104
105/******************************************************************************
106* Set the X-KDE-KALARM-VERSION property in a calendar.
107*/
108#ifndef KALARMCAL_USE_KRESOURCES
109void setKAlarmVersion(const Calendar::Ptr& calendar)
110{
111 calendar->setCustomProperty(APPNAME, VERSION_PROPERTY, QString::fromLatin1(KAEvent::currentCalendarVersionString()));
112}
113#else
114void setKAlarmVersion(CalendarLocal& calendar)
115{
116 calendar.setCustomProperty(APPNAME, VERSION_PROPERTY, QString::fromLatin1(KAEvent::currentCalendarVersionString()));
117}
118#endif
119
120/******************************************************************************
121* Check the version of KAlarm which wrote a calendar file, and convert it in
122* memory to the current KAlarm format if possible. The storage file is not
123* updated. The compatibility of the calendar format is indicated by the return
124* value.
125*/
126#ifndef KALARMCAL_USE_KRESOURCES
127int updateVersion(const FileStorage::Ptr& fileStorage, QString& versionString)
128#else
129int updateVersion(CalendarLocal& calendar, const QString& localFile, QString& versionString)
130#endif
131{
132 QString subVersion;
133#ifndef KALARMCAL_USE_KRESOURCES
134 const int version = Private::readKAlarmVersion(fileStorage, subVersion, versionString);
135#else
136 const int version = Private::readKAlarmVersion(calendar, localFile, subVersion, versionString);
137#endif
138 if (version == CurrentFormat)
139 return CurrentFormat; // calendar is in the current KAlarm format
140 if (version == IncompatibleFormat || version > KAEvent::currentCalendarVersion())
141 return IncompatibleFormat; // calendar was created by another program, or an unknown version of KAlarm
142
143 // Calendar was created by an earlier version of KAlarm.
144 // Convert it to the current format.
145#ifndef KALARMCAL_USE_KRESOURCES
146 const QString localFile = fileStorage->fileName();
147#endif
148 int ver = version;
149 if (version == KAlarmCal::Version(0,5,7) && !localFile.isEmpty())
150 {
151 // KAlarm version 0.5.7 - check whether times are stored in UTC, in which
152 // case it is the KDE 3.0.0 version, which needs adjustment of summer times.
153 if (isUTC(localFile))
154 ver = -version;
155 kDebug() << "KAlarm version 0.5.7 (" << (ver < 0 ? "" : "non-") << "UTC)";
156 }
157 else
158 kDebug() << "KAlarm version" << version;
159
160 // Convert events to current KAlarm format for when/if the calendar is saved
161#ifndef KALARMCAL_USE_KRESOURCES
162 KAEvent::convertKCalEvents(fileStorage->calendar(), ver);
163#else
164 KAEvent::convertKCalEvents(calendar, ver);
165#endif
166 return version;
167}
168
169} // namespace KACalendar
170
171/******************************************************************************
172* Return the KAlarm version which wrote the calendar which has been loaded.
173* The format is, for example, 000507 for 0.5.7.
174* Reply = CurrentFormat if the calendar was created by the current version of KAlarm
175* = IncompatibleFormat if it was created by KAlarm pre-0.3.5, or another program
176* = version number if created by another KAlarm version.
177*/
178#ifndef KALARMCAL_USE_KRESOURCES
179int Private::readKAlarmVersion(const FileStorage::Ptr& fileStorage, QString& subVersion, QString& versionString)
180#else
181int Private::readKAlarmVersion(CalendarLocal& calendar, const QString& localFile, QString& subVersion, QString& versionString)
182#endif
183{
184 subVersion.clear();
185#ifndef KALARMCAL_USE_KRESOURCES
186 Calendar::Ptr calendar = fileStorage->calendar();
187 versionString = calendar->customProperty(KACalendar::APPNAME, VERSION_PROPERTY);
188 kDebug() << "File=" << fileStorage->fileName() << ", version=" << versionString;
189
190#else
191 versionString = calendar.customProperty(KACalendar::APPNAME, VERSION_PROPERTY);
192#endif
193
194 if (versionString.isEmpty())
195 {
196 // Pre-KAlarm 1.4 defined the KAlarm version number in the PRODID field.
197 // If another application has written to the file, this may not be present.
198#ifndef KALARMCAL_USE_KRESOURCES
199 const QString prodid = calendar->productId();
200#else
201 const QString prodid = calendar.productId();
202#endif
203 if (prodid.isEmpty())
204 {
205 // Check whether the calendar file is empty, in which case
206 // it can be written to freely.
207#ifndef KALARMCAL_USE_KRESOURCES
208 const QFileInfo fi(fileStorage->fileName());
209#else
210 const QFileInfo fi(localFile);
211#endif
212 if (!fi.size())
213 return KACalendar::CurrentFormat;
214 }
215
216 // Find the KAlarm identifier
217 QString progname = QLatin1String(" KAlarm ");
218 int i = prodid.indexOf(progname, 0, Qt::CaseInsensitive);
219 if (i < 0)
220 {
221 // Older versions used KAlarm's translated name in the product ID, which
222 // could have created problems using a calendar in different locales.
223 progname = QLatin1String(" ") + i18n("KAlarm") + QLatin1Char(' ');
224 i = prodid.indexOf(progname, 0, Qt::CaseInsensitive);
225 if (i < 0)
226 return KACalendar::IncompatibleFormat; // calendar wasn't created by KAlarm
227 }
228
229 // Extract the KAlarm version string
230 versionString = prodid.mid(i + progname.length()).trimmed();
231 i = versionString.indexOf(QLatin1Char('/'));
232 const int j = versionString.indexOf(QLatin1Char(' '));
233 if (j >= 0 && j < i)
234 i = j;
235 if (i <= 0)
236 return KACalendar::IncompatibleFormat; // missing version string
237 versionString = versionString.left(i); // 'versionString' now contains the KAlarm version string
238 }
239 if (versionString == QLatin1String(KAEvent::currentCalendarVersionString()))
240 return KACalendar::CurrentFormat; // the calendar is in the current KAlarm format
241 const int ver = KAlarmCal::getVersionNumber(versionString, &subVersion);
242 if (ver == KAEvent::currentCalendarVersion())
243 return KACalendar::CurrentFormat; // the calendar is in the current KAlarm format
244 return KAlarmCal::getVersionNumber(versionString, &subVersion);
245}
246
247/******************************************************************************
248* Check whether the calendar file has its times stored as UTC times,
249* indicating that it was written by the KDE 3.0.0 version of KAlarm 0.5.7.
250* Reply = true if times are stored in UTC
251* = false if the calendar is a vCalendar, times are not UTC, or any error occurred.
252*/
253bool isUTC(const QString& localFile)
254{
255 // Read the calendar file into a string
256 QFile file(localFile);
257 if (!file.open(QIODevice::ReadOnly))
258 return false;
259 QTextStream ts(&file);
260 ts.setCodec("ISO 8859-1");
261 const QByteArray text = ts.readAll().toLocal8Bit();
262 file.close();
263
264 // Extract the CREATED property for the first VEVENT from the calendar
265 const QByteArray BEGIN_VCALENDAR("BEGIN:VCALENDAR");
266 const QByteArray BEGIN_VEVENT("BEGIN:VEVENT");
267 const QByteArray CREATED("CREATED:");
268 const QList<QByteArray> lines = text.split('\n');
269 for (int i = 0, end = lines.count(); i < end; ++i)
270 {
271 if (lines[i].startsWith(BEGIN_VCALENDAR))
272 {
273 while (++i < end)
274 {
275 if (lines[i].startsWith(BEGIN_VEVENT))
276 {
277 while (++i < end)
278 {
279 if (lines[i].startsWith(CREATED))
280 return lines[i].endsWith('Z');
281 }
282 }
283 }
284 break;
285 }
286 }
287 return false;
288}
289
290//=============================================================================
291
292namespace CalEvent
293{
294
295// Struct to contain static strings, to allow use of K_GLOBAL_STATIC
296// to delete them on program termination.
297struct StaticStrings
298{
299 StaticStrings()
300 : STATUS_PROPERTY("TYPE"),
301 ACTIVE_STATUS(QLatin1String("ACTIVE")),
302 TEMPLATE_STATUS(QLatin1String("TEMPLATE")),
303 ARCHIVED_STATUS(QLatin1String("ARCHIVED")),
304 DISPLAYING_STATUS(QLatin1String("DISPLAYING")),
305 ARCHIVED_UID(QLatin1String("-exp-")),
306 DISPLAYING_UID(QLatin1String("-disp-")),
307 TEMPLATE_UID(QLatin1String("-tmpl-"))
308 {}
309 // Event custom properties.
310 // Note that all custom property names are prefixed with X-KDE-KALARM- in the calendar file.
311 const QByteArray STATUS_PROPERTY; // X-KDE-KALARM-TYPE property
312 const QString ACTIVE_STATUS;
313 const QString TEMPLATE_STATUS;
314 const QString ARCHIVED_STATUS;
315 const QString DISPLAYING_STATUS;
316
317 // Event ID identifiers
318 const QString ARCHIVED_UID;
319 const QString DISPLAYING_UID;
320
321 // Old KAlarm format identifiers
322 const QString TEMPLATE_UID;
323};
324K_GLOBAL_STATIC(StaticStrings, staticStrings)
325
326/******************************************************************************
327* Convert a unique ID to indicate that the event is in a specified calendar file.
328*/
329QString uid(const QString& id, Type status)
330{
331 QString result = id;
332 Type oldType;
333 int i, len;
334 if ((i = result.indexOf(staticStrings->ARCHIVED_UID)) > 0)
335 {
336 oldType = ARCHIVED;
337 len = staticStrings->ARCHIVED_UID.length();
338 }
339 else if ((i = result.indexOf(staticStrings->DISPLAYING_UID)) > 0)
340 {
341 oldType = DISPLAYING;
342 len = staticStrings->DISPLAYING_UID.length();
343 }
344 else
345 {
346 oldType = ACTIVE;
347 i = result.lastIndexOf(QLatin1Char('-'));
348 len = 1;
349 if (i < 0)
350 {
351 i = result.length();
352 len = 0;
353 }
354 else
355 len = 1;
356 }
357 if (status != oldType && i > 0)
358 {
359 QString part;
360 switch (status)
361 {
362 case ARCHIVED: part = staticStrings->ARCHIVED_UID; break;
363 case DISPLAYING: part = staticStrings->DISPLAYING_UID; break;
364 case ACTIVE:
365 case TEMPLATE:
366 case EMPTY:
367 default: part = QLatin1String("-"); break;
368 }
369 result.replace(i, len, part);
370 }
371 return result;
372}
373
374/******************************************************************************
375* Check an event to determine its type - active, archived, template or empty.
376* The default type is active if it contains alarms and there is nothing to
377* indicate otherwise.
378* Note that the mere fact that all an event's alarms have passed does not make
379* an event archived, since it may be that they have not yet been able to be
380* triggered. They will be archived once KAlarm tries to handle them.
381* Do not call this function for the displaying alarm calendar.
382*/
383#ifndef KALARMCAL_USE_KRESOURCES
384Type status(const Event::Ptr& event, QString* param)
385#else
386Type status(const Event* event, QString* param)
387#endif
388{
389 // Set up a static quick lookup for type strings
390 typedef QMap<QString, Type> PropertyMap;
391 static PropertyMap properties;
392 if (properties.isEmpty())
393 {
394 properties[staticStrings->ACTIVE_STATUS] = ACTIVE;
395 properties[staticStrings->TEMPLATE_STATUS] = TEMPLATE;
396 properties[staticStrings->ARCHIVED_STATUS] = ARCHIVED;
397 properties[staticStrings->DISPLAYING_STATUS] = DISPLAYING;
398 }
399
400 if (param)
401 param->clear();
402 if (!event)
403 return EMPTY;
404 const Alarm::List alarms = event->alarms();
405 if (alarms.isEmpty())
406 return EMPTY;
407
408 const QString property = event->customProperty(KACalendar::APPNAME, staticStrings->STATUS_PROPERTY);
409 if (!property.isEmpty())
410 {
411 // There's a X-KDE-KALARM-TYPE property.
412 // It consists of the event type, plus an optional parameter.
413 PropertyMap::ConstIterator it = properties.constFind(property);
414 if (it != properties.constEnd())
415 return it.value();
416 const int i = property.indexOf(QLatin1Char(';'));
417 if (i < 0)
418 return EMPTY;
419 it = properties.constFind(property.left(i));
420 if (it == properties.constEnd())
421 return EMPTY;
422 if (param)
423 *param = property.mid(i + 1);
424 return it.value();
425 }
426
427 // The event either wasn't written by KAlarm, or was written by a pre-2.0 version.
428 // Check first for an old KAlarm format, which indicated the event type in its UID.
429 const QString uid = event->uid();
430 if (uid.indexOf(staticStrings->ARCHIVED_UID) > 0)
431 return ARCHIVED;
432 if (uid.indexOf(staticStrings->TEMPLATE_UID) > 0)
433 return TEMPLATE;
434
435 // Otherwise, assume it's an active alarm
436 return ACTIVE;
437}
438
439/******************************************************************************
440* Set the event's type - active, archived, template, etc.
441* If a parameter is supplied, it will be appended as a second parameter to the
442* custom property.
443*/
444#ifndef KALARMCAL_USE_KRESOURCES
445void setStatus(const Event::Ptr& event, Type status, const QString& param)
446#else
447void setStatus(Event* event, Type status, const QString& param)
448#endif
449{
450 if (!event)
451 return;
452 QString text;
453 switch (status)
454 {
455 case ACTIVE: text = staticStrings->ACTIVE_STATUS; break;
456 case TEMPLATE: text = staticStrings->TEMPLATE_STATUS; break;
457 case ARCHIVED: text = staticStrings->ARCHIVED_STATUS; break;
458 case DISPLAYING: text = staticStrings->DISPLAYING_STATUS; break;
459 default:
460 event->removeCustomProperty(KACalendar::APPNAME, staticStrings->STATUS_PROPERTY);
461 return;
462 }
463 if (!param.isEmpty())
464 text += QLatin1Char(';') + param;
465 event->setCustomProperty(KACalendar::APPNAME, staticStrings->STATUS_PROPERTY, text);
466}
467
468#ifndef KALARMCAL_USE_KRESOURCES
469Type type(const QString& mimeType)
470{
471 if (mimeType == MIME_ACTIVE)
472 return ACTIVE;
473 if (mimeType == MIME_ARCHIVED)
474 return ARCHIVED;
475 if (mimeType == MIME_TEMPLATE)
476 return TEMPLATE;
477 return EMPTY;
478}
479
480Types types(const QStringList& mimeTypes)
481{
482 Types types = 0;
483 foreach (const QString& type, mimeTypes)
484 {
485 if (type == MIME_ACTIVE)
486 types |= ACTIVE;
487 if (type == MIME_ARCHIVED)
488 types |= ARCHIVED;
489 if (type == MIME_TEMPLATE)
490 types |= TEMPLATE;
491 }
492 return types;
493}
494
495QString mimeType(Type type)
496{
497 switch (type)
498 {
499 case ACTIVE: return MIME_ACTIVE;
500 case ARCHIVED: return MIME_ARCHIVED;
501 case TEMPLATE: return MIME_TEMPLATE;
502 default: return QString();
503 }
504}
505
506QStringList mimeTypes(Types types)
507{
508 QStringList mimes;
509 for (int i = 1; types; i <<= 1)
510 {
511 if (types & i)
512 {
513 mimes += mimeType(Type(i));
514 types &= ~i;
515 }
516 }
517 return mimes;
518}
519#endif
520
521} // namespace CalEvent
522
523} // namespace KAlarmCal
524
525// vim: et sw=4:
alarm.h
Akonadi::Collection
KAlarmCal::KAEvent::currentCalendarVersion
static int currentCalendarVersion()
Return the current KAlarm calendar storage format version.
Definition kaevent.cpp:446
KAlarmCal::KAEvent::currentCalendarVersionString
static QByteArray currentCalendarVersionString()
Return the current KAlarm calendar storage format version.
Definition kaevent.cpp:445
KAlarmCal::KAEvent::convertKCalEvents
static bool convertKCalEvents(const KCalCore::Calendar::Ptr &, int calendarVersion)
If a calendar was written by a previous version of KAlarm, do any necessary format conversions on the...
Definition kaevent.cpp:5240
KCalCore::Alarm::List
QVector< Ptr > List
KCalCore::Calendar::Ptr
QSharedPointer< Calendar > Ptr
KCalCore::Event
KCalCore::Event::Ptr
QSharedPointer< Event > Ptr
KCalCore::FileStorage::Ptr
QSharedPointer< FileStorage > Ptr
event.h
memorycalendar.h
KAlarmCal::CalEvent::type
Type type(const QString &mimeType)
Return the alarm Type for a mime type string.
Definition kacalendar.cpp:469
KAlarmCal::CalEvent::mimeType
QString mimeType(Type type)
Return the mime type string corresponding to an alarm Type.
Definition kacalendar.cpp:495
KAlarmCal::CalEvent::mimeTypes
QStringList mimeTypes(Types types)
Return the mime type strings corresponding to alarm Types.
Definition kacalendar.cpp:506
KAlarmCal::CalEvent::Type
Type
The category of an event, indicated by the middle part of its UID.
Definition kacalendar.h:156
KAlarmCal::CalEvent::DISPLAYING
@ DISPLAYING
the event is currently being displayed
Definition kacalendar.h:161
KAlarmCal::CalEvent::TEMPLATE
@ TEMPLATE
the event is an alarm template
Definition kacalendar.h:160
KAlarmCal::CalEvent::ACTIVE
@ ACTIVE
the event is currently active
Definition kacalendar.h:158
KAlarmCal::CalEvent::ARCHIVED
@ ARCHIVED
the event is archived
Definition kacalendar.h:159
KAlarmCal::CalEvent::EMPTY
@ EMPTY
the event has no alarms
Definition kacalendar.h:157
KAlarmCal::CalEvent::types
Types types(const QStringList &mimeTypes)
Return the alarm Types for a list of mime type strings.
Definition kacalendar.cpp:480
KAlarmCal::KACalendar::updateVersion
int updateVersion(const FileStorage::Ptr &fileStorage, QString &versionString)
Check the version of KAlarm which wrote a calendar file, and convert it in memory to the current KAla...
Definition kacalendar.cpp:127
KAlarmCal::KACalendar::CurrentFormat
@ CurrentFormat
current KAlarm format
Definition kacalendar.h:97
KAlarmCal::KACalendar::IncompatibleFormat
@ IncompatibleFormat
not written by KAlarm, or a newer KAlarm version
Definition kacalendar.h:101
KAlarmCal::KACalendar::setProductId
void setProductId(const QByteArray &progName, const QByteArray &progVersion)
Set the program name and version for use in calendars.
Definition kacalendar.cpp:95
KAlarmCal::KACalendar::icalProductId
QByteArray icalProductId()
Return the product ID string for use in calendars.
Definition kacalendar.cpp:100
KAlarmCal::KACalendar::APPNAME
const QByteArray APPNAME
The application name ("KALARM") used in calendar properties.
KAlarmCal::KACalendar::setKAlarmVersion
void setKAlarmVersion(const Calendar::Ptr &calendar)
Set the KAlarm version custom property for a calendar.
Definition kacalendar.cpp:109
KCalCore
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Wed Jan 24 2024 00:00:00 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KAlarm Library

Skip menu "KAlarm Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.14.10 API Reference

Skip menu "kdepimlibs-4.14.10 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal