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

KDE's Doxygen guidelines are available online.