libkcal Library API Documentation

icalformat.cpp

00001 /*
00002     This file is part of libkcal.
00003     Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018     Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include <qdatetime.h>
00022 #include <qstring.h>
00023 #include <qptrlist.h>
00024 #include <qregexp.h>
00025 #include <qclipboard.h>
00026 #include <qfile.h>
00027 #include <qtextstream.h>
00028 
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 
00032 extern "C" {
00033   #include <ical.h>
00034   #include <icalss.h>
00035   #include <icalparser.h>
00036   #include <icalrestriction.h>
00037 }
00038 
00039 #include "calendar.h"
00040 #include "journal.h"
00041 
00042 #include "icalformat.h"
00043 #include "icalformatimpl.h"
00044 
00045 #define _ICAL_VERSION "2.0"
00046 
00047 using namespace KCal;
00048 
00049 ICalFormat::ICalFormat()
00050 {
00051   mImpl = new ICalFormatImpl( this );
00052 
00053   mTimeZoneId = "UTC";
00054   mUtc = true;
00055 }
00056 
00057 ICalFormat::~ICalFormat()
00058 {
00059   delete mImpl;
00060 }
00061 
00062 bool ICalFormat::load( Calendar *calendar, const QString &fileName)
00063 {
00064   kdDebug(5800) << "ICalFormat::load() " << fileName << endl;
00065 
00066   clearException();
00067 
00068   QFile file( fileName );
00069   if (!file.open( IO_ReadOnly ) ) {
00070     kdDebug(5800) << "ICalFormat::load() load error" << endl;
00071     setException(new ErrorFormat(ErrorFormat::LoadError));
00072     return false;
00073   }
00074   QTextStream ts( &file );
00075   QString text = ts.read();
00076   file.close();
00077 
00078   return fromString( calendar, text );
00079 }
00080 
00081 
00082 bool ICalFormat::save( Calendar *calendar, const QString &fileName )
00083 {
00084   kdDebug(5800) << "ICalFormat::save(): " << fileName << endl;
00085 
00086   clearException();
00087 
00088   QString text = toString( calendar );
00089 
00090   if ( text.isNull() ) return false;
00091 
00092   // TODO: write backup file
00093 
00094   QFile file( fileName );
00095   if (!file.open( IO_WriteOnly ) ) {
00096     setException(new ErrorFormat(ErrorFormat::SaveError,
00097                  i18n("Could not open file '%1'").arg(fileName)));
00098     return false;
00099   }
00100   QTextStream ts( &file );
00101   ts << text;
00102   file.close();
00103 
00104   return true;
00105 }
00106 
00107 bool ICalFormat::fromString( Calendar *cal, const QString &text )
00108 {
00109   setTimeZone( cal->timeZoneId(), !cal->isLocalTime() );
00110 
00111   // Get first VCALENDAR component.
00112   // TODO: Handle more than one VCALENDAR or non-VCALENDAR top components
00113   icalcomponent *calendar;
00114 
00115   calendar = icalcomponent_new_from_string( text.local8Bit().data());
00116   //  kdDebug(5800) << "Error: " << icalerror_perror() << endl;
00117   if (!calendar) {
00118     kdDebug(5800) << "ICalFormat::load() parse error" << endl;
00119     setException(new ErrorFormat(ErrorFormat::ParseErrorIcal));
00120     return false;
00121   }
00122 
00123   bool success = true;
00124 
00125   if (icalcomponent_isa(calendar) != ICAL_VCALENDAR_COMPONENT) {
00126     kdDebug(5800) << "ICalFormat::load(): No VCALENDAR component found" << endl;
00127     setException(new ErrorFormat(ErrorFormat::NoCalendar));
00128     success = false;
00129   } else {
00130     // put all objects into their proper places
00131     if ( !mImpl->populate( cal, calendar ) ) {
00132       kdDebug(5800) << "ICalFormat::load(): Could not populate calendar" << endl;
00133       if ( !exception() ) {
00134         setException(new ErrorFormat(ErrorFormat::ParseErrorKcal));
00135       }
00136       success = false;
00137     } else
00138       mLoadedProductId = mImpl->loadedProductId();
00139   }
00140 
00141   icalcomponent_free( calendar );
00142 
00143   return success;
00144 }
00145 
00146 QString ICalFormat::toString( Calendar *cal )
00147 {
00148   setTimeZone( cal->timeZoneId(), !cal->isLocalTime() );
00149 
00150   icalcomponent *calendar = mImpl->createCalendarComponent();
00151 
00152   icalcomponent *component;
00153 
00154   // todos
00155   QPtrList<Todo> todoList = cal->rawTodos();
00156   QPtrListIterator<Todo> qlt(todoList);
00157   for (; qlt.current(); ++qlt) {
00158     component = mImpl->writeTodo(qlt.current());
00159     icalcomponent_add_component(calendar,component);
00160   }
00161 
00162   // events
00163   QPtrList<Event> events = cal->rawEvents();
00164   Event *ev;
00165   for(ev=events.first();ev;ev=events.next()) {
00166     component = mImpl->writeEvent(ev);
00167     icalcomponent_add_component(calendar,component);
00168   }
00169 
00170   // journals
00171   QPtrList<Journal> journals = cal->journals();
00172   Journal *j;
00173   for(j=journals.first();j;j=journals.next()) {
00174     component = mImpl->writeJournal(j);
00175     icalcomponent_add_component(calendar,component);
00176   }
00177 
00178   const char *text = icalcomponent_as_ical_string( calendar );
00179 
00180   icalcomponent_free( calendar );
00181 
00182   if (!text) {
00183     setException(new ErrorFormat(ErrorFormat::SaveError,
00184                  i18n("libical error")));
00185     return QString::null;
00186   }
00187 
00188   return QString::fromLocal8Bit( text );
00189 }
00190 
00191 QString ICalFormat::toString( Incidence *incidence )
00192 {
00193   icalcomponent *component;
00194 
00195   component = mImpl->writeIncidence( incidence );
00196 
00197   const char *text = icalcomponent_as_ical_string( component );
00198 
00199   icalcomponent_free( component );
00200 
00201   return QString::fromLocal8Bit( text );
00202 }
00203 
00204 QString ICalFormat::toString( Recurrence *recurrence )
00205 {
00206   icalproperty *property;
00207   property = mImpl->writeRecurrenceRule( recurrence );
00208   const char *text = icalproperty_as_ical_string( property );
00209   icalproperty_free( property );
00210   return QString::fromLocal8Bit( text );
00211 }
00212 
00213 bool ICalFormat::fromString( Recurrence * recurrence, const QString& rrule )
00214 {
00215   bool success = true;
00216   icalerror_clear_errno();
00217   struct icalrecurrencetype recur = icalrecurrencetype_from_string( rrule );
00218   if ( icalerrno != ICAL_NO_ERROR ) {
00219     kdDebug() << "Recurrence parsing error: " << icalerror_strerror( icalerrno ) << endl;
00220     success = false;
00221   }
00222 
00223   if ( success ) {
00224     mImpl->readRecurrence( recur, recurrence );
00225   }
00226 
00227   return success;
00228 }
00229 
00230 
00231 QString ICalFormat::createScheduleMessage(IncidenceBase *incidence,
00232                                           Scheduler::Method method)
00233 {
00234   icalcomponent *message = mImpl->createScheduleComponent(incidence,method);
00235 
00236   QString messageText = icalcomponent_as_ical_string(message);
00237 
00238 #if 0
00239   kdDebug(5800) << "ICalFormat::createScheduleMessage: message START\n"
00240             << messageText
00241             << "ICalFormat::createScheduleMessage: message END" << endl;
00242 #endif
00243 
00244   return messageText;
00245 }
00246 
00247 ScheduleMessage *ICalFormat::parseScheduleMessage( Calendar *cal,
00248                                                    const QString &messageText )
00249 {
00250   clearException();
00251 
00252   if (messageText.isEmpty()) return 0;
00253 
00254   icalcomponent *message;
00255   message = icalparser_parse_string(messageText.local8Bit());
00256 
00257   if (!message) return 0;
00258 
00259   icalproperty *m = icalcomponent_get_first_property(message,
00260                                                      ICAL_METHOD_PROPERTY);
00261 
00262   if (!m) return 0;
00263 
00264   icalcomponent *c;
00265 
00266   IncidenceBase *incidence = 0;
00267   c = icalcomponent_get_first_component(message,ICAL_VEVENT_COMPONENT);
00268   if (c) {
00269     incidence = mImpl->readEvent(c);
00270   }
00271 
00272   c = icalcomponent_get_first_component(message,ICAL_VTODO_COMPONENT);
00273   if (c) {
00274     incidence = mImpl->readTodo(c);
00275   }
00276 
00277   c = icalcomponent_get_first_component(message,ICAL_VFREEBUSY_COMPONENT);
00278   if (c) {
00279     incidence = mImpl->readFreeBusy(c);
00280   }
00281 
00282   if (!incidence) {
00283     kdDebug() << "ICalFormat:parseScheduleMessage: object is not a freebusy, event or todo" << endl;
00284     return 0;
00285   }
00286 
00287   kdDebug(5800) << "ICalFormat::parseScheduleMessage() getting method..." << endl;
00288 
00289   icalproperty_method icalmethod = icalproperty_get_method(m);
00290   Scheduler::Method method;
00291 
00292   switch (icalmethod) {
00293     case ICAL_METHOD_PUBLISH:
00294       method = Scheduler::Publish;
00295       break;
00296     case ICAL_METHOD_REQUEST:
00297       method = Scheduler::Request;
00298       break;
00299     case ICAL_METHOD_REFRESH:
00300       method = Scheduler::Refresh;
00301       break;
00302     case ICAL_METHOD_CANCEL:
00303       method = Scheduler::Cancel;
00304       break;
00305     case ICAL_METHOD_ADD:
00306       method = Scheduler::Add;
00307       break;
00308     case ICAL_METHOD_REPLY:
00309       method = Scheduler::Reply;
00310       break;
00311     case ICAL_METHOD_COUNTER:
00312       method = Scheduler::Counter;
00313       break;
00314     case ICAL_METHOD_DECLINECOUNTER:
00315       method = Scheduler::Declinecounter;
00316       break;
00317     default:
00318       method = Scheduler::NoMethod;
00319       kdDebug(5800) << "ICalFormat::parseScheduleMessage(): Unknow method" << endl;
00320       break;
00321   }
00322 
00323   kdDebug(5800) << "ICalFormat::parseScheduleMessage() restriction..." << endl;
00324 
00325   if (!icalrestriction_check(message)) {
00326     setException(new ErrorFormat(ErrorFormat::Restriction,
00327                                    Scheduler::methodName(method) + ": " +
00328                                    mImpl->extractErrorProperty(c)));
00329     return 0;
00330   }
00331 
00332   icalcomponent *calendarComponent = mImpl->createCalendarComponent();
00333 
00334   Incidence *existingIncidence = cal->event(incidence->uid());
00335   if (existingIncidence) {
00336     // TODO: check, if cast is required, or if it can be done by virtual funcs.
00337     if (existingIncidence->type() == "Todo") {
00338       Todo *todo = static_cast<Todo *>(existingIncidence);
00339       icalcomponent_add_component(calendarComponent,
00340                                   mImpl->writeTodo(todo));
00341     }
00342     if (existingIncidence->type() == "Event") {
00343       Event *event = static_cast<Event *>(existingIncidence);
00344       icalcomponent_add_component(calendarComponent,
00345                                   mImpl->writeEvent(event));
00346     }
00347   } else {
00348     calendarComponent = 0;
00349   }
00350 
00351   kdDebug(5800) << "ICalFormat::parseScheduleMessage() classify..." << endl;
00352 
00353   icalclass result = icalclassify(message,calendarComponent,(char *)"");
00354 
00355   kdDebug(5800) << "ICalFormat::parseScheduleMessage() returning..." << endl;
00356 
00357   ScheduleMessage::Status status;
00358 
00359   switch (result) {
00360     case ICAL_PUBLISH_NEW_CLASS:
00361       status = ScheduleMessage::PublishNew;
00362       break;
00363     case ICAL_OBSOLETE_CLASS:
00364       status = ScheduleMessage::Obsolete;
00365       break;
00366     case ICAL_REQUEST_NEW_CLASS:
00367       status = ScheduleMessage::RequestNew;
00368       break;
00369     case ICAL_REQUEST_UPDATE_CLASS:
00370       status = ScheduleMessage::RequestUpdate;
00371       break;
00372     case ICAL_UNKNOWN_CLASS:
00373     default:
00374       status = ScheduleMessage::Unknown;
00375       break;
00376   }
00377 
00378   return new ScheduleMessage(incidence,method,status);
00379 }
00380 
00381 void ICalFormat::setTimeZone( const QString &id, bool utc )
00382 {
00383   mTimeZoneId = id;
00384   mUtc = utc;
00385 }
00386 
00387 QString ICalFormat::timeZoneId() const
00388 {
00389   return mTimeZoneId;
00390 }
00391 
00392 bool ICalFormat::utc() const
00393 {
00394   return mUtc;
00395 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sat Oct 18 02:47:03 2003 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001