KCalendarCore

icalformat.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the kcalcore library.
3 
4  SPDX-FileCopyrightText: 2001 Cornelius Schumacher <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 /**
9  @file
10  This file is part of the API for handling calendar data and
11  defines the ICalFormat class.
12 
13  @brief
14  iCalendar format implementation: a layer of abstraction for libical.
15 
16  @author Cornelius Schumacher <[email protected]>
17 */
18 #include "icalformat.h"
19 #include "calendar_p.h"
20 #include "icalformat_p.h"
21 #include "icaltimezones_p.h"
22 #include "kcalendarcore_debug.h"
23 #include "memorycalendar.h"
24 
25 #include <QFile>
26 #include <QSaveFile>
27 #include <QTimeZone>
28 
29 extern "C" {
30 #include <libical/ical.h>
31 #include <libical/icalmemory.h>
32 #include <libical/icalparser.h>
33 #include <libical/icalrestriction.h>
34 #include <libical/icalss.h>
35 }
36 
37 using namespace KCalendarCore;
38 
39 //@cond PRIVATE
40 class Q_DECL_HIDDEN KCalendarCore::ICalFormat::Private
41 {
42 public:
43  Private(ICalFormat *parent)
44  : mImpl(new ICalFormatImpl(parent))
45  , mTimeZone(QTimeZone::utc())
46  {
47  }
48  ~Private()
49  {
50  delete mImpl;
51  }
52  ICalFormatImpl *mImpl = nullptr;
53  QTimeZone mTimeZone;
54 };
55 //@endcond
56 
58  : d(new Private(this))
59 {
60 }
61 
63 {
64  icalmemory_free_ring();
65  delete d;
66 }
67 
68 bool ICalFormat::load(const Calendar::Ptr &calendar, const QString &fileName)
69 {
70  qCDebug(KCALCORE_LOG) << fileName;
71 
73 
74  QFile file(fileName);
75  if (!file.open(QIODevice::ReadOnly)) {
76  qCritical() << "load error: unable to open " << fileName;
78  return false;
79  }
80  const QByteArray text = file.readAll().trimmed();
81  file.close();
82 
83  if (!text.isEmpty()) {
84  if (!fromRawString(calendar, text, false, fileName)) {
85  qCWarning(KCALCORE_LOG) << fileName << " is not a valid iCalendar file";
87  return false;
88  }
89  }
90 
91  // Note: we consider empty files to be valid
92 
93  return true;
94 }
95 
96 bool ICalFormat::save(const Calendar::Ptr &calendar, const QString &fileName)
97 {
98  qCDebug(KCALCORE_LOG) << fileName;
99 
100  clearException();
101 
102  QString text = toString(calendar);
103  if (text.isEmpty()) {
104  return false;
105  }
106 
107  // Write backup file
108  const QString backupFile = fileName + QLatin1Char('~');
109  QFile::remove(backupFile);
110  QFile::copy(fileName, backupFile);
111 
112  QSaveFile file(fileName);
113  if (!file.open(QIODevice::WriteOnly)) {
114  qCritical() << "file open error: " << file.errorString() << ";filename=" << fileName;
115  setException(new Exception(Exception::SaveErrorOpenFile, QStringList(fileName)));
116 
117  return false;
118  }
119 
120  // Convert to UTF8 and save
121  QByteArray textUtf8 = text.toUtf8();
122  file.write(textUtf8.data(), textUtf8.size());
123  // QSaveFile doesn't report a write error when the device is full (see Qt
124  // bug 75077), so check that the data can actually be written.
125  if (!file.flush()) {
126  qCDebug(KCALCORE_LOG) << "file write error (flush failed)";
127  setException(new Exception(Exception::SaveErrorSaveFile, QStringList(fileName)));
128  return false;
129  }
130 
131  if (!file.commit()) {
132  qCDebug(KCALCORE_LOG) << "file finalize error:" << file.errorString();
133  setException(new Exception(Exception::SaveErrorSaveFile, QStringList(fileName)));
134 
135  return false;
136  }
137 
138  return true;
139 }
140 
141 bool ICalFormat::fromString(const Calendar::Ptr &cal, const QString &string, bool deleted, const QString &notebook)
142 {
143  return fromRawString(cal, string.toUtf8(), deleted, notebook);
144 }
145 
147 {
148  // Let's defend const correctness until the very gates of hell^Wlibical
149  icalcomponent *calendar = icalcomponent_new_from_string(const_cast<char *>(string.constData()));
150  if (!calendar) {
151  qCritical() << "parse error from icalcomponent_new_from_string. string=" << QString::fromLatin1(string);
153  return Incidence::Ptr();
154  }
155 
156  ICalTimeZoneCache tzCache;
157  ICalTimeZoneParser parser(&tzCache);
158  parser.parse(calendar);
159 
160  Incidence::Ptr incidence;
161  if (icalcomponent_isa(calendar) == ICAL_VCALENDAR_COMPONENT) {
162  incidence = d->mImpl->readOneIncidence(calendar, &tzCache);
163  } else if (icalcomponent_isa(calendar) == ICAL_XROOT_COMPONENT) {
164  icalcomponent *comp = icalcomponent_get_first_component(calendar, ICAL_VCALENDAR_COMPONENT);
165  if (comp) {
166  incidence = d->mImpl->readOneIncidence(comp, &tzCache);
167  }
168  }
169 
170  if (!incidence) {
171  qCDebug(KCALCORE_LOG) << "No VCALENDAR component found";
173  }
174 
175  icalcomponent_free(calendar);
176  icalmemory_free_ring();
177 
178  return incidence;
179 }
180 
181 bool ICalFormat::fromRawString(const Calendar::Ptr &cal, const QByteArray &string, bool deleted, const QString &notebook)
182 {
183  Q_UNUSED(notebook);
184  // Get first VCALENDAR component.
185  // TODO: Handle more than one VCALENDAR or non-VCALENDAR top components
186  icalcomponent *calendar;
187 
188  // Let's defend const correctness until the very gates of hell^Wlibical
189  calendar = icalcomponent_new_from_string(const_cast<char *>(string.constData()));
190  if (!calendar) {
191  qCritical() << "parse error from icalcomponent_new_from_string. string=" << QString::fromLatin1(string);
193  return false;
194  }
195 
196  bool success = true;
197 
198  if (icalcomponent_isa(calendar) == ICAL_XROOT_COMPONENT) {
199  icalcomponent *comp;
200  for (comp = icalcomponent_get_first_component(calendar, ICAL_VCALENDAR_COMPONENT); comp;
201  comp = icalcomponent_get_next_component(calendar, ICAL_VCALENDAR_COMPONENT)) {
202  // put all objects into their proper places
203  if (!d->mImpl->populate(cal, comp, deleted)) {
204  qCritical() << "Could not populate calendar";
205  if (!exception()) {
207  }
208  success = false;
209  } else {
210  setLoadedProductId(d->mImpl->loadedProductId());
211  }
212  }
213  } else if (icalcomponent_isa(calendar) != ICAL_VCALENDAR_COMPONENT) {
214  qCDebug(KCALCORE_LOG) << "No VCALENDAR component found";
216  success = false;
217  } else {
218  // put all objects into their proper places
219  if (!d->mImpl->populate(cal, calendar, deleted)) {
220  qCDebug(KCALCORE_LOG) << "Could not populate calendar";
221  if (!exception()) {
223  }
224  success = false;
225  } else {
226  setLoadedProductId(d->mImpl->loadedProductId());
227  }
228  }
229 
230  icalcomponent_free(calendar);
231  icalmemory_free_ring();
232 
233  return success;
234 }
235 
237 {
238  MemoryCalendar::Ptr cal(new MemoryCalendar(d->mTimeZone));
239  fromString(cal, string);
240 
241  const Incidence::List list = cal->incidences();
242  return !list.isEmpty() ? list.first() : Incidence::Ptr();
243 }
244 
245 QString ICalFormat::toString(const Calendar::Ptr &cal, const QString &notebook, bool deleted)
246 {
247  icalcomponent *calendar = d->mImpl->createCalendarComponent(cal);
248  icalcomponent *component;
249 
250  QVector<QTimeZone> tzUsedList;
251  TimeZoneEarliestDate earliestTz;
252 
253  // todos
254  Todo::List todoList = deleted ? cal->deletedTodos() : cal->rawTodos();
255  for (auto it = todoList.cbegin(), end = todoList.cend(); it != end; ++it) {
256  if (!deleted || !cal->todo((*it)->uid(), (*it)->recurrenceId())) {
257  // use existing ones, or really deleted ones
258  if (notebook.isEmpty() || (!cal->notebook(*it).isEmpty() && notebook.endsWith(cal->notebook(*it)))) {
259  component = d->mImpl->writeTodo(*it, &tzUsedList);
260  icalcomponent_add_component(calendar, component);
261  ICalTimeZoneParser::updateTzEarliestDate((*it), &earliestTz);
262  }
263  }
264  }
265  // events
266  Event::List events = deleted ? cal->deletedEvents() : cal->rawEvents();
267  for (auto it = events.cbegin(), end = events.cend(); it != end; ++it) {
268  if (!deleted || !cal->event((*it)->uid(), (*it)->recurrenceId())) {
269  // use existing ones, or really deleted ones
270  if (notebook.isEmpty() || (!cal->notebook(*it).isEmpty() && notebook.endsWith(cal->notebook(*it)))) {
271  component = d->mImpl->writeEvent(*it, &tzUsedList);
272  icalcomponent_add_component(calendar, component);
273  ICalTimeZoneParser::updateTzEarliestDate((*it), &earliestTz);
274  }
275  }
276  }
277 
278  // journals
279  Journal::List journals = deleted ? cal->deletedJournals() : cal->rawJournals();
280  for (auto it = journals.cbegin(), end = journals.cend(); it != end; ++it) {
281  if (!deleted || !cal->journal((*it)->uid(), (*it)->recurrenceId())) {
282  // use existing ones, or really deleted ones
283  if (notebook.isEmpty() || (!cal->notebook(*it).isEmpty() && notebook.endsWith(cal->notebook(*it)))) {
284  component = d->mImpl->writeJournal(*it, &tzUsedList);
285  icalcomponent_add_component(calendar, component);
286  ICalTimeZoneParser::updateTzEarliestDate((*it), &earliestTz);
287  }
288  }
289  }
290 
291  // time zones
292  if (todoList.isEmpty() && events.isEmpty() && journals.isEmpty()) {
293  // no incidences means no used timezones, use all timezones
294  // this will export a calendar having only timezone definitions
295  tzUsedList = cal->d->mTimeZones;
296  }
297  for (const auto &qtz : qAsConst(tzUsedList)) {
298  if (qtz != QTimeZone::utc()) {
299  icaltimezone *tz = ICalTimeZoneParser::icaltimezoneFromQTimeZone(qtz, earliestTz[qtz]);
300  if (!tz) {
301  qCritical() << "bad time zone";
302  } else {
303  component = icalcomponent_new_clone(icaltimezone_get_component(tz));
304  icalcomponent_add_component(calendar, component);
305  icaltimezone_free(tz, 1);
306  }
307  }
308  }
309 
310  char *const componentString = icalcomponent_as_ical_string_r(calendar);
311  const QString &text = QString::fromUtf8(componentString);
312  free(componentString);
313 
314  icalcomponent_free(calendar);
315  icalmemory_free_ring();
316 
317  if (text.isEmpty()) {
318  setException(new Exception(Exception::LibICalError));
319  }
320 
321  return text;
322 }
323 
325 {
326  MemoryCalendar::Ptr cal(new MemoryCalendar(d->mTimeZone));
327  cal->addIncidence(Incidence::Ptr(incidence->clone()));
328  return toString(cal.staticCast<Calendar>());
329 }
330 
332 {
333  return QString::fromUtf8(toRawString(incidence));
334 }
335 
337 {
338  TimeZoneList tzUsedList;
339 
340  icalcomponent *component = d->mImpl->writeIncidence(incidence, iTIPRequest, &tzUsedList);
341 
342  QByteArray text = icalcomponent_as_ical_string(component);
343 
344  TimeZoneEarliestDate earliestTzDt;
345  ICalTimeZoneParser::updateTzEarliestDate(incidence, &earliestTzDt);
346 
347  // time zones
348  for (const auto &qtz : qAsConst(tzUsedList)) {
349  if (qtz != QTimeZone::utc()) {
350  icaltimezone *tz = ICalTimeZoneParser::icaltimezoneFromQTimeZone(qtz, earliestTzDt[qtz]);
351  if (!tz) {
352  qCritical() << "bad time zone";
353  } else {
354  icalcomponent *tzcomponent = icaltimezone_get_component(tz);
355  icalcomponent_add_component(component, component);
356  text.append(icalcomponent_as_ical_string(tzcomponent));
357  icaltimezone_free(tz, 1);
358  }
359  }
360  }
361 
362  icalcomponent_free(component);
363 
364  return text;
365 }
366 
368 {
369  icalproperty *property = icalproperty_new_rrule(d->mImpl->writeRecurrenceRule(recurrence));
370  QString text = QString::fromUtf8(icalproperty_as_ical_string(property));
371  icalproperty_free(property);
372  return text;
373 }
374 
375 bool ICalFormat::fromString(RecurrenceRule *recurrence, const QString &rrule)
376 {
377  if (!recurrence) {
378  return false;
379  }
380  bool success = true;
381  icalerror_clear_errno();
382  struct icalrecurrencetype recur = icalrecurrencetype_from_string(rrule.toLatin1().constData());
383  if (icalerrno != ICAL_NO_ERROR) {
384  qCDebug(KCALCORE_LOG) << "Recurrence parsing error:" << icalerror_strerror(icalerrno);
385  success = false;
386  }
387 
388  if (success) {
389  d->mImpl->readRecurrence(recur, recurrence);
390  }
391 
392  return success;
393 }
394 
396 {
397  icalcomponent *message = nullptr;
398 
399  if (incidence->type() == Incidence::TypeEvent || incidence->type() == Incidence::TypeTodo) {
400  Incidence::Ptr i = incidence.staticCast<Incidence>();
401 
402  // Recurring events need timezone information to allow proper calculations
403  // across timezones with different DST.
404  const bool useUtcTimes = !i->recurs();
405 
406  const bool hasSchedulingId = (i->schedulingID() != i->uid());
407 
408  const bool incidenceNeedChanges = (useUtcTimes || hasSchedulingId);
409 
410  if (incidenceNeedChanges) {
411  // The incidence need changes, so clone it before we continue
412  i = Incidence::Ptr(i->clone());
413 
414  // Handle conversion to UTC times
415  if (useUtcTimes) {
416  i->shiftTimes(QTimeZone::utc(), QTimeZone::utc());
417  }
418 
419  // Handle scheduling ID being present
420  if (hasSchedulingId) {
421  // We have a separation of scheduling ID and UID
422  i->setSchedulingID(QString(), i->schedulingID());
423  }
424 
425  // Build the message with the cloned incidence
426  message = d->mImpl->createScheduleComponent(i, method);
427  }
428  }
429 
430  if (message == nullptr) {
431  message = d->mImpl->createScheduleComponent(incidence, method);
432  }
433 
434  QString messageText = QString::fromUtf8(icalcomponent_as_ical_string(message));
435 
436  icalcomponent_free(message);
437  return messageText;
438 }
439 
441 {
442  clearException();
443 
444  icalcomponent *message = icalparser_parse_string(str.toUtf8().constData());
445 
446  if (!message) {
447  return FreeBusy::Ptr();
448  }
449 
450  FreeBusy::Ptr freeBusy;
451 
452  icalcomponent *c = nullptr;
453  for (c = icalcomponent_get_first_component(message, ICAL_VFREEBUSY_COMPONENT); c != nullptr;
454  c = icalcomponent_get_next_component(message, ICAL_VFREEBUSY_COMPONENT)) {
455  FreeBusy::Ptr fb = d->mImpl->readFreeBusy(c);
456 
457  if (freeBusy) {
458  freeBusy->merge(fb);
459  } else {
460  freeBusy = fb;
461  }
462  }
463 
464  if (!freeBusy) {
465  qCDebug(KCALCORE_LOG) << "object is not a freebusy.";
466  }
467 
468  icalcomponent_free(message);
469 
470  return freeBusy;
471 }
472 
474 {
475  setTimeZone(cal->timeZone());
476  clearException();
477 
478  if (messageText.isEmpty()) {
479  setException(new Exception(Exception::ParseErrorEmptyMessage));
480  return ScheduleMessage::Ptr();
481  }
482 
483  icalcomponent *message = icalparser_parse_string(messageText.toUtf8().constData());
484 
485  if (!message) {
486  setException(new Exception(Exception::ParseErrorUnableToParse));
487 
488  return ScheduleMessage::Ptr();
489  }
490 
491  icalproperty *m = icalcomponent_get_first_property(message, ICAL_METHOD_PROPERTY);
492  if (!m) {
493  setException(new Exception(Exception::ParseErrorMethodProperty));
494 
495  return ScheduleMessage::Ptr();
496  }
497 
498  // Populate the message's time zone collection with all VTIMEZONE components
499  ICalTimeZoneCache tzlist;
500  ICalTimeZoneParser parser(&tzlist);
501  parser.parse(message);
502 
503  IncidenceBase::Ptr incidence;
504  icalcomponent *c = icalcomponent_get_first_component(message, ICAL_VEVENT_COMPONENT);
505  if (c) {
506  incidence = d->mImpl->readEvent(c, &tzlist).staticCast<IncidenceBase>();
507  }
508 
509  if (!incidence) {
510  c = icalcomponent_get_first_component(message, ICAL_VTODO_COMPONENT);
511  if (c) {
512  incidence = d->mImpl->readTodo(c, &tzlist).staticCast<IncidenceBase>();
513  }
514  }
515 
516  if (!incidence) {
517  c = icalcomponent_get_first_component(message, ICAL_VJOURNAL_COMPONENT);
518  if (c) {
519  incidence = d->mImpl->readJournal(c, &tzlist).staticCast<IncidenceBase>();
520  }
521  }
522 
523  if (!incidence) {
524  c = icalcomponent_get_first_component(message, ICAL_VFREEBUSY_COMPONENT);
525  if (c) {
526  incidence = d->mImpl->readFreeBusy(c).staticCast<IncidenceBase>();
527  }
528  }
529 
530  if (!incidence) {
531  qCDebug(KCALCORE_LOG) << "object is not a freebusy, event, todo or journal";
532  setException(new Exception(Exception::ParseErrorNotIncidence));
533 
534  return ScheduleMessage::Ptr();
535  }
536 
537  icalproperty_method icalmethod = icalproperty_get_method(m);
538  iTIPMethod method;
539 
540  switch (icalmethod) {
541  case ICAL_METHOD_PUBLISH:
542  method = iTIPPublish;
543  break;
544  case ICAL_METHOD_REQUEST:
545  method = iTIPRequest;
546  break;
547  case ICAL_METHOD_REFRESH:
548  method = iTIPRefresh;
549  break;
550  case ICAL_METHOD_CANCEL:
551  method = iTIPCancel;
552  break;
553  case ICAL_METHOD_ADD:
554  method = iTIPAdd;
555  break;
556  case ICAL_METHOD_REPLY:
557  method = iTIPReply;
558  break;
559  case ICAL_METHOD_COUNTER:
560  method = iTIPCounter;
561  break;
562  case ICAL_METHOD_DECLINECOUNTER:
563  method = iTIPDeclineCounter;
564  break;
565  default:
566  method = iTIPNoMethod;
567  qCDebug(KCALCORE_LOG) << "Unknown method";
568  break;
569  }
570 
571  if (!icalrestriction_check(message)) {
572  qCWarning(KCALCORE_LOG) << "\nkcalcore library reported a problem while parsing:";
573  qCWarning(KCALCORE_LOG) << ScheduleMessage::methodName(method) << ":" << d->mImpl->extractErrorProperty(c);
574  }
575 
576  Incidence::Ptr existingIncidence = cal->incidence(incidence->uid());
577 
578  icalcomponent *calendarComponent = nullptr;
579  if (existingIncidence) {
580  calendarComponent = d->mImpl->createCalendarComponent(cal);
581 
582  // TODO: check, if cast is required, or if it can be done by virtual funcs.
583  // TODO: Use a visitor for this!
584  if (existingIncidence->type() == Incidence::TypeTodo) {
585  Todo::Ptr todo = existingIncidence.staticCast<Todo>();
586  icalcomponent_add_component(calendarComponent, d->mImpl->writeTodo(todo));
587  }
588  if (existingIncidence->type() == Incidence::TypeEvent) {
589  Event::Ptr event = existingIncidence.staticCast<Event>();
590  icalcomponent_add_component(calendarComponent, d->mImpl->writeEvent(event));
591  }
592  } else {
593  icalcomponent_free(message);
594  return ScheduleMessage::Ptr(new ScheduleMessage(incidence, method, ScheduleMessage::Unknown));
595  }
596 
597  icalproperty_xlicclass result = icalclassify(message, calendarComponent, static_cast<const char *>(""));
598 
600 
601  switch (result) {
602  case ICAL_XLICCLASS_PUBLISHNEW:
604  break;
605  case ICAL_XLICCLASS_PUBLISHUPDATE:
607  break;
608  case ICAL_XLICCLASS_OBSOLETE:
609  status = ScheduleMessage::Obsolete;
610  break;
611  case ICAL_XLICCLASS_REQUESTNEW:
613  break;
614  case ICAL_XLICCLASS_REQUESTUPDATE:
616  break;
617  case ICAL_XLICCLASS_UNKNOWN:
618  default:
619  status = ScheduleMessage::Unknown;
620  break;
621  }
622 
623  icalcomponent_free(message);
624  icalcomponent_free(calendarComponent);
625 
626  return ScheduleMessage::Ptr(new ScheduleMessage(incidence, method, status));
627 }
628 
630 {
631  d->mTimeZone = timeZone;
632 }
633 
635 {
636  return d->mTimeZone;
637 }
638 
640 {
641  return d->mTimeZone.id();
642 }
643 
644 void ICalFormat::virtual_hook(int id, void *data)
645 {
646  Q_UNUSED(id);
647  Q_UNUSED(data);
648  Q_ASSERT(false);
649 }
Represents the main calendar class.
Definition: calendar.h:129
No calendar component found.
Definition: exceptions.h:52
QByteArray trimmed() const const
bool flush()
bool remove()
This file is part of the API for handling calendar data and defines the MemoryCalendar class...
Incidence::Ptr readIncidence(const QByteArray &string)
Parses a bytearray, returning the first iCal component as an Incidence, ignoring timezone information...
Definition: icalformat.cpp:146
QString errorString() const const
void setLoadedProductId(const QString &id)
Sets the PRODID string loaded from calendar file.
Definition: calformat.cpp:100
bool isEmpty() const const
QSharedPointer< Incidence > Ptr
A shared pointer to an Incidence.
Definition: incidence.h:114
QVector::const_iterator cend() const const
virtual bool open(QIODevice::OpenMode mode) override
T & first()
Event, to-do or freebusy reply to request.
static QString methodName(iTIPMethod method)
Returns a machine-readable (not translatable) name for a iTIP method.
ICalFormat()
Constructor a new iCalendar Format object.
Definition: icalformat.cpp:57
bool copy(const QString &newName)
void clearException()
Clears the exception status.
Definition: calformat.cpp:62
A Scheduling message class.
Event or to-do submit counter proposal.
An abstract class that provides a common base for all calendar incidence classes. ...
Definition: incidencebase.h:97
QString fromUtf8(const char *str, int size)
iTIPMethod
iTIP methods.
bool commit()
Event or to-do description update request.
~ICalFormat() override
Destructor.
Definition: icalformat.cpp:62
This class provides an Event in the sense of RFC2445.
Definition: event.h:29
QTimeZone utc()
QByteArray timeZoneId() const
Returns the timezone id string used by the iCalendar; an empty string if the iCalendar does not have ...
Definition: icalformat.cpp:639
bool isEmpty() const const
const char * constData() const const
QByteArray readAll()
QString createScheduleMessage(const IncidenceBase::Ptr &incidence, iTIPMethod method)
Creates a scheduling message string for an Incidence.
Definition: icalformat.cpp:395
FreeBusy::Ptr parseFreeBusy(const QString &string)
Converts a QString into a FreeBusy object.
Definition: icalformat.cpp:440
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
QVector::const_iterator cbegin() const const
Provides a To-do in the sense of RFC2445.
Definition: todo.h:30
bool save(const Calendar::Ptr &calendar, const QString &fileName) override
Definition: icalformat.cpp:96
virtual bool open(QIODevice::OpenMode mode) override
void virtual_hook(int id, void *data) override
Definition: icalformat.cpp:644
QByteArray & append(char ch)
QTimeZone timeZone() const
Returns the iCalendar time zone.
Definition: icalformat.cpp:634
QString toString(const Calendar::Ptr &calendar, const QString &notebook=QString(), bool deleted=false) override
Definition: icalformat.cpp:245
bool load(const Calendar::Ptr &calendar, const QString &fileName) override
Definition: icalformat.cpp:68
QByteArray toLatin1() const const
QString toICalString(const Incidence::Ptr &incidence)
Converts an Incidence to iCalendar formatted text.
Definition: icalformat.cpp:324
Event, to-do, journal or freebusy posting.
Exception base class, currently used as a fancy kind of error code and not as an C++ exception...
Definition: exceptions.h:41
iCalendar format implementation.
Definition: icalformat.h:43
Event, to-do or journal cancellation notice.
bool isEmpty() const const
virtual void close() override
Event or to-do decline a counter proposal.
This class provides a calendar stored in memory.
Event, to-do or freebusy scheduling request.
char * data()
void setException(Exception *error)
Sets an exception that is to be used by the functions of this class to report errors.
Definition: calformat.cpp:68
qint64 write(const char *data, qint64 maxSize)
QString fromLatin1(const char *str, int size)
QSharedPointer< FreeBusy > Ptr
A shared pointer to a FreeBusy object.
Definition: freebusy.h:50
bool fromRawString(const Calendar::Ptr &calendar, const QByteArray &string, bool deleted=false, const QString &notebook=QString()) override
Definition: icalformat.cpp:181
Event, to-do or journal additional property request.
This class represents a recurrence rule for a calendar incidence.
Provides the abstract base class common to non-FreeBusy (Events, To-dos, Journals) calendar component...
Definition: incidence.h:56
int size() const const
QSharedPointer< X > staticCast() const const
QSharedPointer< ScheduleMessage > Ptr
A shared pointer to a ScheduleMessage.
QByteArray toRawString(const Incidence::Ptr &incidence)
Converts an Incidence to a QByteArray.
Definition: icalformat.cpp:336
This file is part of the API for handling calendar data and defines the ICalFormat class...
bool fromString(const Calendar::Ptr &calendar, const QString &string, bool deleted=false, const QString &notebook=QString()) override
Definition: icalformat.cpp:141
Namespace for all KCalendarCore types.
Definition: alarm.h:36
Exception * exception() const
Returns an exception, if there is any, containing information about the last error that occurred...
Definition: calformat.cpp:74
ScheduleMessage::Ptr parseScheduleMessage(const Calendar::Ptr &calendar, const QString &string)
Parses a Calendar scheduling message string into ScheduleMessage object.
Definition: icalformat.cpp:473
QByteArray toUtf8() const const
void setTimeZone(const QTimeZone &timeZone)
Sets the iCalendar time zone.
Definition: icalformat.cpp:629
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Fri Sep 24 2021 22:51:50 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.