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

KCalCore Library

icalformat.cpp
Go to the documentation of this file.
00001 /*
00002   This file is part of the kcalcore library.
00003 
00004   Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
00005 
00006   This library is free software; you can redistribute it and/or
00007   modify it under the terms of the GNU Library General Public
00008   License as published by the Free Software Foundation; either
00009   version 2 of the License, or (at your option) any later version.
00010 
00011   This library is distributed in the hope that it will be useful,
00012   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014   Library General Public License for more details.
00015 
00016   You should have received a copy of the GNU Library General Public License
00017   along with this library; see the file COPYING.LIB.  If not, write to
00018   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019   Boston, MA 02110-1301, USA.
00020 */
00031 #include "icalformat.h"
00032 #include "icalformat_p.h"
00033 #include "icaltimezones.h"
00034 #include "freebusy.h"
00035 #include "memorycalendar.h"
00036 
00037 #include <KDebug>
00038 #include <KSaveFile>
00039 
00040 #include <QtCore/QFile>
00041 
00042 extern "C" {
00043   #include <libical/ical.h>
00044   #include <libical/icalss.h>
00045   #include <libical/icalparser.h>
00046   #include <libical/icalrestriction.h>
00047   #include <libical/icalmemory.h>
00048 }
00049 
00050 using namespace KCalCore;
00051 
00052 //@cond PRIVATE
00053 class KCalCore::ICalFormat::Private
00054 {
00055   public:
00056     Private( ICalFormat *parent )
00057       : mImpl( new ICalFormatImpl( parent ) ),
00058         mTimeSpec( KDateTime::UTC )
00059     {}
00060     ~Private()  { delete mImpl; }
00061     ICalFormatImpl *mImpl;
00062     KDateTime::Spec mTimeSpec;
00063 };
00064 //@endcond
00065 
00066 ICalFormat::ICalFormat()
00067   : d( new Private( this ) )
00068 {
00069 }
00070 
00071 ICalFormat::~ICalFormat()
00072 {
00073   icalmemory_free_ring();
00074   delete d;
00075 }
00076 
00077 bool ICalFormat::load( const Calendar::Ptr &calendar, const QString &fileName )
00078 {
00079   kDebug() << fileName;
00080 
00081   clearException();
00082 
00083   QFile file( fileName );
00084   if ( !file.open( QIODevice::ReadOnly ) ) {
00085     kDebug() << "load error";
00086     setException( new Exception( Exception::LoadError ) );
00087     return false;
00088   }
00089   QTextStream ts( &file );
00090   ts.setCodec( "UTF-8" );
00091   QByteArray text = ts.readAll().trimmed().toUtf8();
00092   file.close();
00093 
00094   if ( text.isEmpty() ) {
00095     // empty files are valid
00096     return true;
00097   } else {
00098     return fromRawString( calendar, text, false, fileName );
00099   }
00100 }
00101 
00102 bool ICalFormat::save( const Calendar::Ptr &calendar, const QString &fileName )
00103 {
00104   kDebug() << fileName;
00105 
00106   clearException();
00107 
00108   QString text = toString( calendar );
00109   if ( text.isEmpty() ) {
00110     return false;
00111   }
00112 
00113   // Write backup file
00114   KSaveFile::backupFile( fileName );
00115 
00116   KSaveFile file( fileName );
00117   if ( !file.open() ) {
00118     kDebug() << "file open error:" << file.errorString();
00119     setException( new Exception( Exception::SaveErrorOpenFile,
00120                                  QStringList( fileName ) ) );
00121 
00122     return false;
00123   }
00124 
00125   // Convert to UTF8 and save
00126   QByteArray textUtf8 = text.toUtf8();
00127   file.write( textUtf8.data(), textUtf8.size() );
00128 
00129   if ( !file.finalize() ) {
00130     kDebug() << "file finalize error:" << file.errorString();
00131     setException( new Exception( Exception::SaveErrorSaveFile,
00132                                  QStringList( fileName ) ) );
00133 
00134     return false;
00135   }
00136 
00137   return true;
00138 }
00139 
00140 bool ICalFormat::fromString( const Calendar::Ptr &cal, const QString &string,
00141                              bool deleted, const QString &notebook )
00142 {
00143   return fromRawString( cal, string.toUtf8(), deleted, notebook );
00144 }
00145 
00146 bool ICalFormat::fromRawString( const Calendar::Ptr &cal, const QByteArray &string,
00147                                 bool deleted, const QString &notebook )
00148 {
00149   Q_UNUSED( notebook );
00150   // Get first VCALENDAR component.
00151   // TODO: Handle more than one VCALENDAR or non-VCALENDAR top components
00152   icalcomponent *calendar;
00153 
00154   // Let's defend const correctness until the very gates of hell^Wlibical
00155   calendar = icalcomponent_new_from_string( const_cast<char*>( ( const char * )string ) );
00156   if ( !calendar ) {
00157     kDebug() << "parse error";
00158     setException( new Exception( Exception::ParseErrorIcal ) );
00159     return false;
00160   }
00161 
00162   bool success = true;
00163 
00164   if ( icalcomponent_isa( calendar ) == ICAL_XROOT_COMPONENT ) {
00165     icalcomponent *comp;
00166     for ( comp = icalcomponent_get_first_component( calendar, ICAL_VCALENDAR_COMPONENT );
00167           comp; comp = icalcomponent_get_next_component( calendar, ICAL_VCALENDAR_COMPONENT ) ) {
00168       // put all objects into their proper places
00169       if ( !d->mImpl->populate( cal, comp, deleted ) ) {
00170         kDebug() << "Could not populate calendar";
00171         if ( !exception() ) {
00172           setException( new Exception( Exception::ParseErrorKcal ) );
00173         }
00174         success = false;
00175       } else {
00176         setLoadedProductId( d->mImpl->loadedProductId() );
00177       }
00178     }
00179   } else if ( icalcomponent_isa( calendar ) != ICAL_VCALENDAR_COMPONENT ) {
00180     kDebug() << "No VCALENDAR component found";
00181     setException( new Exception( Exception::NoCalendar ) );
00182     success = false;
00183   } else {
00184     // put all objects into their proper places
00185     if ( !d->mImpl->populate( cal, calendar, deleted ) ) {
00186       kDebug() << "Could not populate calendar";
00187       if ( !exception() ) {
00188         setException( new Exception( Exception::ParseErrorKcal ) );
00189       }
00190       success = false;
00191     } else {
00192       setLoadedProductId( d->mImpl->loadedProductId() );
00193     }
00194   }
00195 
00196   icalcomponent_free( calendar );
00197   icalmemory_free_ring();
00198 
00199   return success;
00200 }
00201 
00202 Incidence::Ptr ICalFormat::fromString( const QString &string )
00203 {
00204   MemoryCalendar::Ptr cal( new MemoryCalendar( d->mTimeSpec ) );
00205   fromString( cal, string );
00206 
00207   Incidence::Ptr ical;
00208   Event::List elist = cal->events();
00209   if ( elist.count() > 0 ) {
00210     ical = elist.first();
00211   } else {
00212     Todo::List tlist = cal->todos();
00213     if ( tlist.count() > 0 ) {
00214       ical = tlist.first();
00215     } else {
00216       Journal::List jlist = cal->journals();
00217       if ( jlist.count() > 0 ) {
00218         ical = jlist.first();
00219       }
00220     }
00221   }
00222 
00223   return ical ? Incidence::Ptr( ical->clone() ) : Incidence::Ptr();
00224 }
00225 
00226 QString ICalFormat::toString( const Calendar::Ptr &cal,
00227                               const QString &notebook, bool deleted )
00228 {
00229   icalcomponent *calendar = d->mImpl->createCalendarComponent( cal );
00230   icalcomponent *component;
00231 
00232   ICalTimeZones *tzlist = cal->timeZones();  // time zones possibly used in the calendar
00233   ICalTimeZones tzUsedList;                  // time zones actually used in the calendar
00234 
00235   // todos
00236   Todo::List todoList = deleted ? cal->deletedTodos() : cal->rawTodos();
00237   Todo::List::ConstIterator it;
00238   for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
00239     if ( !deleted || !cal->todo( (*it)->uid(), (*it)->recurrenceId() ) ) {
00240       // use existing ones, or really deleted ones
00241       if ( notebook.isEmpty() ||
00242            ( !cal->notebook( *it ).isEmpty() && notebook.endsWith( cal->notebook( *it ) ) ) ) {
00243         component = d->mImpl->writeTodo( *it, tzlist, &tzUsedList );
00244         icalcomponent_add_component( calendar, component );
00245       }
00246     }
00247   }
00248   // events
00249   Event::List events = deleted ? cal->deletedEvents() : cal->rawEvents();
00250   Event::List::ConstIterator it2;
00251   for ( it2 = events.constBegin(); it2 != events.constEnd(); ++it2 ) {
00252     if ( !deleted || !cal->event( (*it2)->uid(), (*it2)->recurrenceId() ) ) {
00253       // use existing ones, or really deleted ones
00254       if ( notebook.isEmpty() ||
00255            ( !cal->notebook( *it2 ).isEmpty() && notebook.endsWith( cal->notebook( *it2 ) ) ) ) {
00256         component = d->mImpl->writeEvent( *it2, tzlist, &tzUsedList );
00257         icalcomponent_add_component( calendar, component );
00258       }
00259     }
00260   }
00261 
00262   // journals
00263   Journal::List journals = deleted ? cal->deletedJournals() : cal->rawJournals();
00264   Journal::List::ConstIterator it3;
00265   for ( it3 = journals.constBegin(); it3 != journals.constEnd(); ++it3 ) {
00266     if ( !deleted || !cal->journal( (*it3)->uid(), (*it3)->recurrenceId() ) ) {
00267       // use existing ones, or really deleted ones
00268       if ( notebook.isEmpty() ||
00269            ( !cal->notebook( *it3 ).isEmpty() && notebook.endsWith( cal->notebook( *it3 ) ) ) ) {
00270         component = d->mImpl->writeJournal( *it3, tzlist, &tzUsedList );
00271         icalcomponent_add_component( calendar, component );
00272       }
00273     }
00274   }
00275 
00276   // time zones
00277   ICalTimeZones::ZoneMap zones = tzUsedList.zones();
00278   if ( todoList.isEmpty() && events.isEmpty() && journals.isEmpty() ) {
00279     // no incidences means no used timezones, use all timezones
00280     // this will export a calendar having only timezone definitions
00281     zones = tzlist->zones();
00282   }
00283   for ( ICalTimeZones::ZoneMap::ConstIterator it=zones.constBegin();
00284         it != zones.constEnd(); ++it ) {
00285     icaltimezone *tz = (*it).icalTimezone();
00286     if ( !tz ) {
00287       kError() << "bad time zone";
00288     } else {
00289       component = icalcomponent_new_clone( icaltimezone_get_component( tz ) );
00290       icalcomponent_add_component( calendar, component );
00291       icaltimezone_free( tz, 1 );
00292     }
00293   }
00294 
00295   char *const componentString = icalcomponent_as_ical_string_r( calendar );
00296   const QString &text = QString::fromUtf8( componentString );
00297   free(componentString);
00298 
00299   icalcomponent_free( calendar );
00300   icalmemory_free_ring();
00301 
00302   if ( text.isEmpty() ) {
00303     setException( new Exception( Exception::LibICalError ) );
00304   }
00305 
00306   return text;
00307 }
00308 
00309 QString ICalFormat::toICalString( const Incidence::Ptr &incidence )
00310 {
00311   MemoryCalendar::Ptr cal( new MemoryCalendar( d->mTimeSpec ) );
00312   cal->addIncidence( Incidence::Ptr( incidence->clone() ) );
00313   return toString( cal.staticCast<Calendar>() );
00314 }
00315 
00316 QString ICalFormat::toString( const Incidence::Ptr &incidence )
00317 {
00318   return QString::fromUtf8( toRawString( incidence ) );
00319 }
00320 
00321 QByteArray ICalFormat::toRawString( const Incidence::Ptr &incidence )
00322 {
00323   icalcomponent *component;
00324   ICalTimeZones tzlist;
00325   ICalTimeZones tzUsedList;
00326 
00327   component = d->mImpl->writeIncidence( incidence, iTIPRequest, &tzlist, &tzUsedList );
00328 
00329   QByteArray text = icalcomponent_as_ical_string( component );
00330 
00331   // time zones
00332   ICalTimeZones::ZoneMap zones = tzUsedList.zones();
00333   for ( ICalTimeZones::ZoneMap::ConstIterator it=zones.constBegin();
00334         it != zones.constEnd(); ++it ) {
00335     icaltimezone *tz = (*it).icalTimezone();
00336     if ( !tz ) {
00337       kError() << "bad time zone";
00338     } else {
00339       icalcomponent *tzcomponent = icaltimezone_get_component( tz );
00340       icalcomponent_add_component( component, component );
00341       text.append( icalcomponent_as_ical_string( tzcomponent ) );
00342       icaltimezone_free( tz, 1 );
00343     }
00344   }
00345 
00346   icalcomponent_free( component );
00347 
00348   return text;
00349 }
00350 
00351 QString ICalFormat::toString( RecurrenceRule *recurrence )
00352 {
00353   icalproperty *property;
00354   property = icalproperty_new_rrule( d->mImpl->writeRecurrenceRule( recurrence ) );
00355   QString text = QString::fromUtf8( icalproperty_as_ical_string( property ) );
00356   icalproperty_free( property );
00357   return text;
00358 }
00359 
00360 bool ICalFormat::fromString( RecurrenceRule *recurrence, const QString &rrule )
00361 {
00362   if ( !recurrence ) {
00363     return false;
00364   }
00365   bool success = true;
00366   icalerror_clear_errno();
00367   struct icalrecurrencetype recur = icalrecurrencetype_from_string( rrule.toLatin1() );
00368   if ( icalerrno != ICAL_NO_ERROR ) {
00369     kDebug() << "Recurrence parsing error:" << icalerror_strerror( icalerrno );
00370     success = false;
00371   }
00372 
00373   if ( success ) {
00374     d->mImpl->readRecurrence( recur, recurrence );
00375   }
00376 
00377   return success;
00378 }
00379 
00380 QString ICalFormat::createScheduleMessage( const IncidenceBase::Ptr &incidence,
00381                                            iTIPMethod method )
00382 {
00383   icalcomponent *message = 0;
00384 
00385   if ( incidence->type() == Incidence::TypeEvent ||
00386        incidence->type() == Incidence::TypeTodo ) {
00387 
00388     Incidence::Ptr i = incidence.staticCast<Incidence>();
00389 
00390     // Recurring events need timezone information to allow proper calculations
00391     // across timezones with different DST.
00392     const bool useUtcTimes = !i->recurs();
00393 
00394     const bool hasSchedulingId = ( i->schedulingID() != i->uid() );
00395 
00396     const bool incidenceNeedChanges = ( useUtcTimes || hasSchedulingId );
00397 
00398     if ( incidenceNeedChanges ) {
00399       // The incidence need changes, so clone it before we continue
00400       i = Incidence::Ptr( i->clone() );
00401 
00402       // Handle conversion to UTC times
00403       if ( useUtcTimes ) {
00404         i->shiftTimes( KDateTime::Spec::UTC(), KDateTime::Spec::UTC() );
00405       }
00406 
00407       // Handle scheduling ID being present
00408       if ( hasSchedulingId ) {
00409         // We have a separation of scheduling ID and UID
00410         i->setSchedulingID( QString(), i->schedulingID() );
00411 
00412       }
00413 
00414       // Build the message with the cloned incidence
00415       message = d->mImpl->createScheduleComponent( i, method );
00416     }
00417   }
00418 
00419   if ( message == 0 ) {
00420     message = d->mImpl->createScheduleComponent( incidence, method );
00421   }
00422 
00423   QString messageText = QString::fromUtf8( icalcomponent_as_ical_string( message ) );
00424 
00425   icalcomponent_free( message );
00426   return messageText;
00427 }
00428 
00429 FreeBusy::Ptr ICalFormat::parseFreeBusy( const QString &str )
00430 {
00431   clearException();
00432 
00433   icalcomponent *message;
00434   message = icalparser_parse_string( str.toUtf8() );
00435 
00436   if ( !message ) {
00437     return FreeBusy::Ptr();
00438   }
00439 
00440   FreeBusy::Ptr freeBusy;
00441 
00442   icalcomponent *c;
00443   for ( c = icalcomponent_get_first_component( message, ICAL_VFREEBUSY_COMPONENT );
00444         c != 0; c = icalcomponent_get_next_component( message, ICAL_VFREEBUSY_COMPONENT ) ) {
00445     FreeBusy::Ptr fb = d->mImpl->readFreeBusy( c );
00446 
00447     if ( freeBusy ) {
00448       freeBusy->merge( fb );
00449     } else {
00450       freeBusy = fb;
00451     }
00452   }
00453 
00454   if ( !freeBusy ) {
00455     kDebug() << "object is not a freebusy.";
00456   }
00457 
00458   icalcomponent_free( message );
00459 
00460   return freeBusy;
00461 }
00462 
00463 ScheduleMessage::Ptr ICalFormat::parseScheduleMessage( const Calendar::Ptr &cal,
00464                                                        const QString &messageText )
00465 {
00466   setTimeSpec( cal->timeSpec() );
00467   clearException();
00468 
00469   if ( messageText.isEmpty() ) {
00470     setException(
00471       new Exception( Exception::ParseErrorEmptyMessage ) );
00472     return ScheduleMessage::Ptr();
00473   }
00474 
00475   icalcomponent *message;
00476   message = icalparser_parse_string( messageText.toUtf8() );
00477 
00478   if ( !message ) {
00479     setException(
00480       new Exception( Exception::ParseErrorUnableToParse ) );
00481 
00482     return ScheduleMessage::Ptr();
00483   }
00484 
00485   icalproperty *m =
00486     icalcomponent_get_first_property( message, ICAL_METHOD_PROPERTY );
00487   if ( !m ) {
00488     setException(
00489       new Exception( Exception::ParseErrorMethodProperty ) );
00490 
00491     return ScheduleMessage::Ptr();
00492   }
00493 
00494   // Populate the message's time zone collection with all VTIMEZONE components
00495   ICalTimeZones tzlist;
00496   ICalTimeZoneSource tzs;
00497   tzs.parse( message, tzlist );
00498 
00499   icalcomponent *c;
00500 
00501   IncidenceBase::Ptr incidence;
00502   c = icalcomponent_get_first_component( message, ICAL_VEVENT_COMPONENT );
00503   if ( c ) {
00504     incidence = d->mImpl->readEvent( c, &tzlist ).staticCast<IncidenceBase>();
00505   }
00506 
00507   if ( !incidence ) {
00508     c = icalcomponent_get_first_component( message, ICAL_VTODO_COMPONENT );
00509     if ( c ) {
00510       incidence = d->mImpl->readTodo( c, &tzlist ).staticCast<IncidenceBase>();
00511     }
00512   }
00513 
00514   if ( !incidence ) {
00515     c = icalcomponent_get_first_component( message, ICAL_VJOURNAL_COMPONENT );
00516     if ( c ) {
00517       incidence = d->mImpl->readJournal( c, &tzlist ).staticCast<IncidenceBase>();
00518     }
00519   }
00520 
00521   if ( !incidence ) {
00522     c = icalcomponent_get_first_component( message, ICAL_VFREEBUSY_COMPONENT );
00523     if ( c ) {
00524       incidence = d->mImpl->readFreeBusy( c ).staticCast<IncidenceBase>();
00525     }
00526   }
00527 
00528   if ( !incidence ) {
00529     kDebug() << "object is not a freebusy, event, todo or journal";
00530     setException( new Exception( Exception::ParseErrorNotIncidence ) );
00531 
00532     return ScheduleMessage::Ptr();
00533   }
00534 
00535   icalproperty_method icalmethod = icalproperty_get_method( m );
00536   iTIPMethod method;
00537 
00538   switch ( icalmethod ) {
00539   case ICAL_METHOD_PUBLISH:
00540     method = iTIPPublish;
00541     break;
00542   case ICAL_METHOD_REQUEST:
00543     method = iTIPRequest;
00544     break;
00545   case ICAL_METHOD_REFRESH:
00546     method = iTIPRefresh;
00547     break;
00548   case ICAL_METHOD_CANCEL:
00549     method = iTIPCancel;
00550     break;
00551   case ICAL_METHOD_ADD:
00552     method = iTIPAdd;
00553     break;
00554   case ICAL_METHOD_REPLY:
00555     method = iTIPReply;
00556     break;
00557   case ICAL_METHOD_COUNTER:
00558     method = iTIPCounter;
00559     break;
00560   case ICAL_METHOD_DECLINECOUNTER:
00561     method = iTIPDeclineCounter;
00562     break;
00563   default:
00564     method = iTIPNoMethod;
00565     kDebug() << "Unknown method";
00566     break;
00567   }
00568 
00569   if ( !icalrestriction_check( message ) ) {
00570     kWarning() << endl
00571                << "kcalcore library reported a problem while parsing:";
00572     kWarning() << ScheduleMessage::methodName( method ) << ":"  //krazy:exclude=kdebug
00573                << d->mImpl->extractErrorProperty( c );
00574   }
00575 
00576   Incidence::Ptr existingIncidence = cal->incidence( incidence->uid() );
00577 
00578   icalcomponent *calendarComponent = 0;
00579   if ( existingIncidence ) {
00580     calendarComponent = d->mImpl->createCalendarComponent( cal );
00581 
00582     // TODO: check, if cast is required, or if it can be done by virtual funcs.
00583     // TODO: Use a visitor for this!
00584     if ( existingIncidence->type() == Incidence::TypeTodo ) {
00585       Todo::Ptr todo = existingIncidence.staticCast<Todo>();
00586       icalcomponent_add_component( calendarComponent,
00587                                    d->mImpl->writeTodo( todo ) );
00588     }
00589     if ( existingIncidence->type() == Incidence::TypeEvent ) {
00590       Event::Ptr event = existingIncidence.staticCast<Event>();
00591       icalcomponent_add_component( calendarComponent,
00592                                    d->mImpl->writeEvent( event ) );
00593     }
00594   } else {
00595     icalcomponent_free( message );
00596     return ScheduleMessage::Ptr( new ScheduleMessage( incidence, method,
00597                                                       ScheduleMessage::Unknown ) );
00598   }
00599 
00600   icalproperty_xlicclass result =
00601     icalclassify( message, calendarComponent, static_cast<const char *>( "" ) );
00602 
00603   ScheduleMessage::Status status;
00604 
00605   switch ( result ) {
00606   case ICAL_XLICCLASS_PUBLISHNEW:
00607     status = ScheduleMessage::PublishNew;
00608     break;
00609   case ICAL_XLICCLASS_PUBLISHUPDATE:
00610     status = ScheduleMessage::PublishUpdate;
00611     break;
00612   case ICAL_XLICCLASS_OBSOLETE:
00613     status = ScheduleMessage::Obsolete;
00614     break;
00615   case ICAL_XLICCLASS_REQUESTNEW:
00616     status = ScheduleMessage::RequestNew;
00617     break;
00618   case ICAL_XLICCLASS_REQUESTUPDATE:
00619     status = ScheduleMessage::RequestUpdate;
00620     break;
00621   case ICAL_XLICCLASS_UNKNOWN:
00622   default:
00623     status = ScheduleMessage::Unknown;
00624     break;
00625   }
00626 
00627   icalcomponent_free( message );
00628   icalcomponent_free( calendarComponent );
00629 
00630   return ScheduleMessage::Ptr( new ScheduleMessage( incidence, method, status ) );
00631 }
00632 
00633 void ICalFormat::setTimeSpec( const KDateTime::Spec &timeSpec )
00634 {
00635   d->mTimeSpec = timeSpec;
00636 }
00637 
00638 KDateTime::Spec ICalFormat::timeSpec() const
00639 {
00640   return d->mTimeSpec;
00641 }
00642 
00643 QString ICalFormat::timeZoneId() const
00644 {
00645   KTimeZone tz = d->mTimeSpec.timeZone();
00646   return tz.isValid() ? tz.name() : QString();
00647 }
00648 
00649 void ICalFormat::virtual_hook( int id, void *data )
00650 {
00651   Q_UNUSED( id );
00652   Q_UNUSED( data );
00653   Q_ASSERT( false );
00654 }
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu Aug 2 2012 15:24:11 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KCalCore Library

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

kdepimlibs-4.8.5 API Reference

Skip menu "kdepimlibs-4.8.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • 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