libkpimexchange Library API Documentation

exchangedownload.cpp

00001 /*
00002     This file is part of libkpimexchange
00003     Copyright (c) 2002 Jan-Pascal van Best <janpascal@vanbest.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 <qfile.h>
00022 #include <qtextstream.h>
00023 #include <qdatastream.h>
00024 #include <qcstring.h>
00025 #include <qregexp.h>
00026 
00027 #include <kapplication.h>
00028 #include <kconfig.h>
00029 #include <kstandarddirs.h>
00030 #include <kmessagebox.h>
00031 #include <klocale.h>
00032 #include <kaction.h>
00033 #include <kurl.h>
00034 #include <kdebug.h>
00035 #include <krfcdate.h>
00036 
00037 #include <kio/slave.h>
00038 #include <kio/scheduler.h>
00039 #include <kio/slavebase.h>
00040 #include <kio/davjob.h>
00041 #include <kio/http.h>
00042 #include <kio/job.h>
00043 
00044 #include <libkcal/incidence.h>
00045 #include <libkcal/event.h>
00046 #include <libkcal/recurrence.h>
00047 #include <libkcal/icalformat.h>
00048 #include <libkcal/icalformatimpl.h>
00049 #include <libkcal/calendarlocal.h>
00050 
00051 extern "C" {
00052   #include <ical.h>
00053 }
00054 
00055 #include "exchangeclient.h"
00056 #include "exchangeaccount.h"
00057 #include "exchangeprogress.h"
00058 #include "utils.h"
00059 
00060 #include "exchangedownload.h"
00061 
00062 using namespace KPIM;
00063 
00064 ExchangeDownload::ExchangeDownload( ExchangeAccount *account, QWidget *window )
00065   : mWindow( window )
00066 {
00067   kdDebug() << "ExchangeDownload()" << endl;
00068 
00069   mAccount = account;
00070   mDownloadsBusy = 0;
00071   mProgress = 0;
00072   mCalendar = 0;
00073   mFormat = new KCal::ICalFormat();
00074 }
00075 
00076 ExchangeDownload::~ExchangeDownload()
00077 {
00078   kdDebug() << "ExchangeDownload destructor" << endl;
00079   delete mFormat;
00080   if ( mEvents ) delete mEvents;
00081 }
00082 
00083 void ExchangeDownload::download( KCal::Calendar *calendar, const QDate &start,
00084                                  const QDate &end, bool showProgress )
00085 {
00086   mCalendar = calendar;
00087   mEvents = 0;
00088 
00089 #if 0
00090   if( showProgress ) {
00091     //kdDebug() << "Creating progress dialog" << endl;
00092     mProgress = new ExchangeProgress();
00093     mProgress->show();
00094   
00095     connect( this, SIGNAL( startDownload() ), mProgress,
00096              SLOT( slotTransferStarted() ) );
00097     connect( this, SIGNAL(finishDownload() ), mProgress,
00098              SLOT( slotTransferFinished() ) );
00099   }
00100 #endif
00101 
00102   QString sql = dateSelectQuery( start, end.addDays( 1 ) );
00103  
00104   kdDebug() << "Exchange download query: " << endl << sql << endl;
00105 
00106   increaseDownloads();
00107 
00108   kdDebug() << "ExchangeDownload::download() davSearch URL: "
00109             << mAccount->calendarURL() << endl;
00110 
00111   KIO::DavJob *job = KIO::davSearch( mAccount->calendarURL(), "DAV:", "sql",
00112                                      sql, false );
00113   KIO::Scheduler::scheduleJob( job );
00114   job->setWindow( mWindow );
00115   connect( job, SIGNAL( result( KIO::Job * ) ),
00116            SLOT( slotSearchResult( KIO::Job *) ) );
00117 }
00118 
00119 void ExchangeDownload::download( const QDate& start, const QDate& end, bool showProgress )
00120 {
00121   mCalendar = 0;
00122   mEvents = new QPtrList<KCal::Event>;
00123 
00124   if( showProgress ) {
00125     //kdDebug() << "Creating progress dialog" << endl;
00126     mProgress = new ExchangeProgress();
00127     mProgress->show();
00128   
00129     connect( this, SIGNAL(startDownload()), mProgress, SLOT(slotTransferStarted()) );
00130     connect( this, SIGNAL(finishDownload()), mProgress, SLOT(slotTransferFinished()) );
00131   }
00132 
00133   QString sql = dateSelectQuery( start, end.addDays( 1 ) );
00134  
00135   increaseDownloads();
00136 
00137   KIO::DavJob *job = KIO::davSearch( mAccount->calendarURL(), "DAV:", "sql", sql, false );
00138   KIO::Scheduler::scheduleJob(job);
00139   job->setWindow( mWindow );
00140   connect( job, SIGNAL( result( KIO::Job * ) ),
00141            SLOT( slotSearchResult( KIO::Job * ) ) );
00142 }
00143 
00144 // Original query TODO: make query configurable
00145 QString ExchangeDownload::dateSelectQuery( const QDate& start, const QDate& end )
00146 {
00147   QString startString;
00148   startString.sprintf("%04i/%02i/%02i",start.year(),start.month(),start.day());
00149   QString endString;
00150   endString.sprintf("%04i/%02i/%02i",end.year(),end.month(),end.day());
00151   QString sql = 
00152         "SELECT \"DAV:href\", \"urn:schemas:calendar:instancetype\", \"urn:schemas:calendar:uid\"\r\n"
00153         "FROM Scope('shallow traversal of \"\"')\r\n"
00154         "WHERE \"urn:schemas:calendar:dtend\" > '" + startString + "'\r\n"
00155         "AND \"urn:schemas:calendar:dtstart\" < '" + endString + "'";
00156   return sql;
00157 }
00158 
00159 #if 0
00160 // That's the "new" code that breaks with Exchange. It was meant for Opengroupware, but that got its own resource anyway
00161 QString ExchangeDownload::dateSelectQuery( const QDate& start, const QDate& end )
00162 {
00163   QString startString;
00164   startString.sprintf( "%04i-%02i-%02iT00:00:00Z", start.year(),
00165                        start.month(), start.day() );
00166   QString endString;
00167   endString.sprintf( "%04i-%02i-%02iT23:59:59Z", end.year(), end.month(),
00168                      end.day() );
00169   QString sql = 
00170         "SELECT \"DAV:href\", \"urn:schemas:calendar:instancetype\", "
00171         "\"urn:schemas:calendar:uid\"\r\n"
00172         "FROM Scope('shallow traversal of \"\"')\r\n"
00173         "WHERE \"urn:schemas:calendar:dtend\" > '" + startString + "'\r\n"
00174         "AND \"urn:schemas:calendar:dtstart\" < '" + endString + "'";
00175   return sql;
00176 }
00177 #endif
00178 
00179 void ExchangeDownload::slotSearchResult( KIO::Job *job )
00180 {
00181   if ( job->error() ) {
00182     kdError() << "ExchangeDownload::slotSearchResult() error: "
00183               << job->error() << endl;
00184     QString text = i18n("ExchangeDownload\nError accessing '%1': %2")
00185                    .arg( mAccount->calendarURL().prettyURL() )
00186                    .arg( job->errorString() );
00187     KMessageBox::error( 0, text );
00188     finishUp( ExchangeClient::CommunicationError, job );
00189     return;
00190   }
00191   QDomDocument &response = static_cast<KIO::DavJob *>( job )->response();
00192 
00193   kdDebug() << "Search result: " << endl << response.toString() << endl;
00194 
00195   handleAppointments( response, true );
00196   
00197   decreaseDownloads();
00198 }
00199 
00200 void ExchangeDownload::slotMasterResult( KIO::Job *job )
00201 {
00202   if ( job->error() ) {
00203     kdError() << "Error result for Master search: " << job->error() << endl;
00204     job->showErrorDialog( 0 );
00205     finishUp( ExchangeClient::CommunicationError, job );
00206     return;
00207   }
00208   QDomDocument &response = static_cast<KIO::DavJob *>( job )->response();
00209 
00210   kdDebug() << "Search (master) result: " << endl << response.toString() << endl;
00211 
00212   handleAppointments( response, false );
00213   
00214   decreaseDownloads();
00215 }
00216 
00217 void ExchangeDownload::handleAppointments( const QDomDocument &response,
00218                                            bool recurrence )
00219 {
00220   kdDebug() << "Entering handleAppointments" << endl;
00221   int successCount = 0;
00222 
00223   if ( response.documentElement().firstChild().toElement().isNull() ) {
00224     // Got an empty response, but no error. This would mean there are
00225     // no appointments in this time period.
00226     return;
00227   }
00228 
00229   for( QDomElement item = response.documentElement().firstChild().toElement();
00230        !item.isNull();
00231        item = item.nextSibling().toElement() ) {
00232     //kdDebug() << "Current item:" << item.tagName() << endl;
00233     QDomNodeList propstats = item.elementsByTagNameNS( "DAV:", "propstat" );
00234     // kdDebug() << "Item has " << propstats.count() << " propstat children" << endl; 
00235     for( uint i=0; i < propstats.count(); i++ ) {
00236       QDomElement propstat = propstats.item(i).toElement();
00237       QDomElement prop = propstat.namedItem( "prop" ).toElement();
00238       if ( prop.isNull() ) {
00239         kdError() << "Error: no <prop> in response" << endl;
00240     continue;
00241       }
00242 
00243       QDomElement instancetypeElement = prop.namedItem( "instancetype" ).toElement();
00244       if ( instancetypeElement.isNull() ) {
00245         kdError() << "Error: no instance type in Exchange server reply" << endl;
00246         continue;
00247       }
00248       int instanceType = instancetypeElement.text().toInt();
00249       //kdDebug() << "Instance type: " << instanceType << endl;
00250     
00251       if ( recurrence && instanceType > 0 ) {
00252         QDomElement uidElement = prop.namedItem( "uid" ).toElement();
00253         if ( uidElement.isNull() ) {
00254           kdError() << "Error: no uid in Exchange server reply" << endl;
00255           continue;
00256         }
00257         QString uid = uidElement.text();
00258         if ( ! m_uids.contains( uid ) ) {
00259           m_uids[uid] = 1;
00260           handleRecurrence(uid);
00261           successCount++;
00262         }
00263         continue;
00264       }
00265 
00266       QDomElement hrefElement = prop.namedItem( "href" ).toElement();
00267       if ( hrefElement.isNull() ) {
00268         kdError() << "Error: no href in Exchange server reply" << endl;
00269         continue;
00270       }
00271       QString href = hrefElement.text();
00272       KURL url(href);
00273       
00274       kdDebug() << "Getting appointment from url: " << url.prettyURL() << endl;
00275       
00276       readAppointment( toDAV( url ) );
00277       successCount++;
00278     }
00279   }
00280   if ( !successCount ) {
00281     finishUp( ExchangeClient::ServerResponseError,
00282               "WebDAV SEARCH response:\n" + response.toString() );
00283   }
00284 }
00285 
00286 void ExchangeDownload::handleRecurrence( QString uid )
00287 {
00288   // kdDebug() << "Handling recurrence info for uid=" << uid << endl;
00289   QString query = 
00290         "SELECT \"DAV:href\", \"urn:schemas:calendar:instancetype\"\r\n"
00291         "FROM Scope('shallow traversal of \"\"')\r\n"
00292         "WHERE \"urn:schemas:calendar:uid\" = '" + uid + "'\r\n"
00293     " AND (\"urn:schemas:calendar:instancetype\" = 1)\r\n";
00294 //  "      OR \"urn:schemas:calendar:instancetype\" = 3)\r\n" // FIXME: exception are not handled
00295 
00296   // kdDebug() << "Exchange master query: " << endl << query << endl;
00297 
00298   increaseDownloads();
00299  
00300   KIO::DavJob* job = KIO::davSearch( mAccount->calendarURL(), "DAV:", "sql",
00301                                      query, false );
00302   KIO::Scheduler::scheduleJob( job );
00303   job->setWindow( mWindow );
00304   connect( job, SIGNAL( result( KIO::Job * ) ),
00305            SLOT( slotMasterResult( KIO::Job * ) ) );
00306 }
00307 
00308 void ExchangeDownload::readAppointment( const KURL& url )
00309 {
00310   QDomDocument doc;
00311   QDomElement root = addElement( doc, doc, "DAV:", "propfind" );
00312   QDomElement prop = addElement( doc, root, "DAV:", "prop" );
00313   addElement( doc, prop, "urn:schemas:calendar:", "uid" );
00314   addElement( doc, prop, "urn:schemas:calendar:", "timezoneid" );
00315   addElement( doc, prop, "urn:schemas:calendar:", "timezone" );
00316   addElement( doc, prop, "urn:schemas:calendar:", "lastmodified" );
00317   addElement( doc, prop, "urn:schemas:calendar:", "organizer" );
00318   addElement( doc, prop, "urn:schemas:calendar:", "contact" );
00319   addElement( doc, prop, "urn:schemas:httpmail:", "to" );
00320   addElement( doc, prop, "urn:schemas:calendar:", "attendeestatus" );
00321   addElement( doc, prop, "urn:schemas:calendar:", "attendeerole" );
00322   addElement( doc, prop, "DAV:", "isreadonly" );
00323   addElement( doc, prop, "urn:schemas:calendar:", "instancetype" );
00324   addElement( doc, prop, "urn:schemas:calendar:", "created" );
00325   addElement( doc, prop, "urn:schemas:calendar:", "dtstart" );
00326   addElement( doc, prop, "urn:schemas:calendar:", "dtend" );
00327   addElement( doc, prop, "urn:schemas:calendar:", "alldayevent" );
00328   addElement( doc, prop, "urn:schemas:calendar:", "transparent" );
00329   addElement( doc, prop, "urn:schemas:httpmail:", "textdescription" );
00330   addElement( doc, prop, "urn:schemas:httpmail:", "subject" );
00331   addElement( doc, prop, "urn:schemas:calendar:", "location" );
00332   addElement( doc, prop, "urn:schemas:calendar:", "rrule" );
00333   addElement( doc, prop, "urn:schemas:calendar:", "exdate" );
00334   addElement( doc, prop, "urn:schemas:mailheader:", "sensitivity" );
00335   addElement( doc, prop, "urn:schemas:calendar:", "reminderoffset" );
00336   
00337   addElement( doc, prop, "urn:schemas-microsoft-com:office:office",
00338               "Keywords" );
00339 
00340 //  addElement( doc, prop, "", "" );
00341 //  addElement( doc, prop, "DAV:", "" );
00342 //  addElement( doc, prop, "urn:schemas:calendar:", "" );
00343 //  addElement( doc, prop, "urn:content-classes:appointment", "" );
00344 //  addElement( doc, prop, "urn:schemas:httpmail:", "" );
00345 
00346   increaseDownloads();
00347 
00348   KIO::DavJob* job = KIO::davPropFind( url, doc, "0", false );
00349   KIO::Scheduler::scheduleJob( job );
00350   job->setWindow( mWindow );
00351   job->addMetaData( "errorPage", "false" );
00352   connect( job, SIGNAL( result( KIO::Job * ) ),
00353            SLOT( slotPropFindResult( KIO::Job * ) ) );
00354 }
00355 
00356 void ExchangeDownload::slotPropFindResult( KIO::Job *job )
00357 {
00358   kdDebug() << "slotPropFindResult" << endl;
00359 
00360   int error = job->error(); 
00361   if ( error ) {
00362     job->showErrorDialog( 0 );
00363     finishUp( ExchangeClient::CommunicationError, job );
00364     return;
00365   }
00366 
00367   QDomDocument response = static_cast<KIO::DavJob *>( job )->response();
00368   kdDebug() << "Response: " << endl;
00369   kdDebug() << response.toString() << endl;
00370 
00371   QDomElement prop = response.documentElement().namedItem( "response" )
00372                      .namedItem( "propstat" ).namedItem( "prop" ).toElement();
00373  
00374   KCal::Event* event = new KCal::Event();
00375 
00376   QDomElement uidElement = prop.namedItem( "uid" ).toElement();
00377   if ( uidElement.isNull() ) {
00378     kdError() << "Error: no uid in Exchange server reply" << endl;
00379     finishUp( ExchangeClient::IllegalAppointmentError,
00380               "WebDAV server response:\n" + response.toString() );
00381     return;
00382   }
00383   event->setUid( uidElement.text() );
00384   // kdDebug() << "Got UID: " << uidElement.text() << endl;
00385 
00386   QString timezoneid = prop.namedItem( "timezoneid" ).toElement().text();
00387   // kdDebug() << "DEBUG: timezoneid = " << timezoneid << endl;
00388 
00389   QString timezone = prop.namedItem( "timezone" ).toElement().text();
00390   // kdDebug() << "DEBUG: timezone = " << timezone << endl;
00391 
00392   // mFormat is used for parsing recurrence rules.
00393   QString localTimeZoneId;
00394   if ( mCalendar ) {
00395     mFormat->setTimeZone( mCalendar->timeZoneId(), !mCalendar->isLocalTime() );
00396     localTimeZoneId = mCalendar->timeZoneId();
00397   }  else {
00398     localTimeZoneId = "UTC";
00399     // If no mCalendar, stay in UTC
00400   }
00401 
00402   QString lastModified = prop.namedItem( "lastmodified" ).toElement().text();
00403   if ( !lastModified.isEmpty() ) {
00404     QDateTime dt = utcAsZone( QDateTime::fromString( lastModified, Qt::ISODate ), localTimeZoneId );
00405     event->setLastModified( dt );
00406     kdDebug() << "Got lastModified:" << lastModified << ", " << dt.toString() << endl;
00407   }
00408 
00409   QString organizer = prop.namedItem( "organizer" ).toElement().text();
00410   // TODO: Does outlook have a common name? Or does the organizer already contain both?
00411   event->setOrganizer( organizer );
00412   // kdDebug() << "Got organizer: " << organizer << endl;
00413 
00414   // Trying to find attendees, not working yet
00415   QString contact = prop.namedItem( "contact" ).toElement().text();
00416 //  event->setOrganizer( organizer );
00417   // kdDebug() << "DEBUG: Got contact: " << contact << endl;
00418 
00419   // This looks promising for finding attendees
00420   // FIXME: get this to work
00421   QString to = prop.namedItem( "to" ).toElement().text();
00422   // kdDebug() << "DEBUG: Got to: " << to << endl;
00423   QStringList attn = QStringList::split( ",", to ); // This doesn't work: there can be commas between ""
00424   QStringList::iterator it;
00425   for ( it = attn.begin(); it != attn.end(); ++it ) {
00426     // kdDebug() << "    attendee: " << (*it) << endl;
00427     QString name = "";
00428     // KCal::Attendee* a = new KCal::Attendee( name, email );
00429 
00430     // event->addAttendee( a );
00431   }
00432 
00433   QString readonly = prop.namedItem( "isreadonly" ).toElement().text();
00434   event->setReadOnly( readonly == "1" );
00435   kdDebug() << "Got readonly: " << readonly << ":" << (readonly != "0") << endl;
00436 
00437   QString created = prop.namedItem( "created" ).toElement().text();
00438   if ( !created.isEmpty() ) {
00439     QDateTime dt = utcAsZone( QDateTime::fromString( created, Qt::ISODate ),
00440                     localTimeZoneId );
00441     event->setCreated( dt );
00442     kdDebug() << "got created: " << dt.toString() << endl;
00443   }
00444 
00445   QString dtstart = prop.namedItem( "dtstart" ).toElement().text();
00446   if ( !dtstart.isEmpty() ) {
00447     QDateTime dt = utcAsZone( QDateTime::fromString( dtstart, Qt::ISODate ),
00448                               localTimeZoneId );
00449     event->setDtStart( dt );
00450     kdDebug() << "got dtstart: " << dtstart << " becomes in timezone " << dt.toString() << endl;
00451   }
00452 
00453   QString alldayevent = prop.namedItem( "alldayevent" ).toElement().text();
00454   bool floats = alldayevent.toInt() != 0;
00455   event->setFloats( floats );
00456   kdDebug() << "Got alldayevent: \"" << alldayevent << "\":" << floats << endl;
00457 
00458   QString dtend = prop.namedItem( "dtend" ).toElement().text();
00459   if ( !dtend.isEmpty() ) {
00460     QDateTime dt = utcAsZone( QDateTime::fromString( dtend, Qt::ISODate ),
00461                               localTimeZoneId );
00462     // Outlook thinks differently about floating event timing than libkcal
00463     if ( floats ) dt = dt.addDays( -1 );
00464     event->setDtEnd( dt );
00465     kdDebug() << "got dtend: " << dtend << " becomes in timezone " << dt.toString() << endl;
00466   }
00467 
00468   QString transparent = prop.namedItem( "transparent" ).toElement().text();
00469   event->setTransparency( transparent.toInt() > 0 ? KCal::Event::Transparent
00470               : KCal::Event::Opaque );
00471   // kdDebug() << "Got transparent: " << transparent << endl;
00472 
00473   QString description = prop.namedItem( "textdescription" ).toElement().text();
00474   event->setDescription( description );
00475   kdDebug() << "Got description: " << description << endl;
00476 
00477   QString subject = prop.namedItem( "subject" ).toElement().text();
00478   event->setSummary( subject );
00479   kdDebug() << "Got summary: " << subject << endl;
00480 
00481   QString location =  prop.namedItem( "location" ).toElement().text();
00482   event->setLocation( location );
00483   // kdDebug() << "Got location: " << location << endl;
00484 
00485   QString rrule = prop.namedItem( "rrule" ).toElement().text();
00486   kdDebug() << "Got rrule: " << rrule << endl;
00487   if ( !rrule.isEmpty() ) {
00488     // Timezone should be handled automatically 
00489     // because we used mFormat->setTimeZone() earlier
00490     if ( ! mFormat->fromString( event->recurrence(), rrule ) ) {
00491       kdError() << "ERROR parsing rrule " << rrule << endl;
00492     }
00493   }
00494 
00495   QDomElement keywords = prop.namedItem( "Keywords" ).toElement();
00496   QStringList categories;
00497   QDomNodeList list = keywords.elementsByTagNameNS( "xml:", "v" );
00498   for( uint i=0; i < list.count(); i++ ) {
00499     QDomElement item = list.item(i).toElement();
00500     categories.append( item.text() );
00501   }
00502   event->setCategories( categories );
00503   // kdDebug() << "Got categories: " << categories.join( ", " ) << endl;
00504 
00505 
00506   QDomElement exdate = prop.namedItem( "exdate" ).toElement();
00507   KCal::DateList exdates;
00508   list = exdate.elementsByTagNameNS( "xml:", "v" );
00509   for( uint i=0; i < list.count(); i++ ) {
00510     QDomElement item = list.item(i).toElement();
00511     QDate date = utcAsZone( QDateTime::fromString( item.text(), Qt::ISODate ), localTimeZoneId ).date();
00512     exdates.append( date );
00513     // kdDebug() << "Got exdate: " << date.toString() << endl;
00514   }
00515   event->setExDates( exdates );
00516 
00517   // Exchange sentitivity values:
00518   // 0 None
00519   // 1 Personal
00520   // 2 Private
00521   // 3 Company Confidential
00522   QString sensitivity = prop.namedItem( "sensitivity" ).toElement().text();
00523   if ( ! sensitivity.isNull() ) 
00524   switch( sensitivity.toInt() ) {
00525     case 0: event->setSecrecy( KCal::Incidence::SecrecyPublic ); break;
00526     case 1: event->setSecrecy( KCal::Incidence::SecrecyPrivate ); break;
00527     case 2: event->setSecrecy( KCal::Incidence::SecrecyPrivate ); break;
00528     case 3: event->setSecrecy( KCal::Incidence::SecrecyConfidential ); break;
00529     default: kdWarning() << "Unknown sensitivity: " << sensitivity << endl;
00530   }
00531   // kdDebug() << "Got sensitivity: " << sensitivity << endl;
00532 
00533 
00534   QString reminder = prop.namedItem( "reminderoffset" ).toElement().text();
00535   // kdDebug() << "Reminder offset: " << reminder << endl;
00536   if ( !reminder.isEmpty() ) {
00537     // Duration before event in seconds
00538     KCal::Duration offset( - reminder.toInt() );
00539     KCal::Alarm *alarm = event->newAlarm();
00540     alarm->setStartOffset( offset );
00541     alarm->setEnabled( true );
00542     // TODO: multiple alarms; alarm->setType( KCal::Alarm::xxxx );
00543   }
00545     //Alarm* newAlarm();
00547     //void addAlarm(Alarm*);
00548 
00550     //void setRelatedTo(Incidence *relatedTo);
00552     //void addRelation(Incidence *);
00553 
00555     //void setAttachments(const QStringList &attachments);
00556  
00558     //void setResources(const QStringList &resources);
00559 
00561     //void setPriority(int priority);
00562 
00568     //void addAttendee(Attendee *a, bool doupdate=true );
00569 
00570   // THE FOLLOWING EVENT PROPERTIES ARE NOT READ
00571 
00572   // Revision ID in webdav is a String, not an int
00574     //void setRevision(int rev);
00575 
00576   // Problem: When you sync Outlook to a Palm, the conduit splits up
00577   // multi-day events into single-day events WITH ALL THE SAME UID
00578   // Grrrrrrr.
00579   if ( mCalendar ) {
00580     KCal::Event *oldEvent = mCalendar->event( event->uid() );
00581     if ( oldEvent ) {
00582       kdWarning() << "Already got his event, replace it..." << endl;
00583       mCalendar->deleteEvent( oldEvent );
00584     }
00585     kdDebug() << "ADD EVENT" << endl;
00586     mCalendar->addEvent( event );
00587   } else {
00588     kdDebug() << "EMIT gotEvent" << endl;
00589     emit gotEvent( event, static_cast<KIO::DavJob *>( job )->url() );
00590 //    mEvents->append( event );
00591   }
00592 
00593   decreaseDownloads();
00594 }
00595 
00596 void ExchangeDownload::increaseDownloads()
00597 {
00598   mDownloadsBusy++;
00599   emit startDownload();
00600 }
00601 
00602 void ExchangeDownload::decreaseDownloads()
00603 {
00604   mDownloadsBusy--;
00605   // kdDebug() << "Download finished, waiting for " << mDownloadsBusy << " more" << endl;
00606   emit finishDownload();
00607   if ( mDownloadsBusy == 0 ) {
00608     kdDebug() << "All downloads finished" << endl;
00609     finishUp( ExchangeClient::ResultOK );
00610   }
00611 }
00612 
00613 void ExchangeDownload::finishUp( int result, const QString &moreInfo )
00614 {
00615   kdDebug() << "ExchangeDownload::finishUp() " << result << " "
00616             << moreInfo << endl;
00617 
00618   if ( mCalendar ) mCalendar->setModified( true );
00619   // Disconnect from progress bar
00620   if ( mProgress ) {
00621     disconnect( this, 0, mProgress, 0 );
00622     disconnect( mProgress, 0, this, 0 );
00623     mProgress->delayedDestruct();
00624   }
00625 
00626 //  if ( mEvents ) {
00627 //    emit finished( this, result, moreInfo, *mEvents );
00628 //  } else {
00629     emit finished( this, result, moreInfo );
00630 //  }
00631 }
00632 
00633 void ExchangeDownload::finishUp( int result, KIO::Job *job )
00634 {
00635   finishUp( result, QString("WebDAV job error code = ") +
00636                     QString::number( job->error() ) + ";\n" + "\"" +
00637                     job->errorString() + "\"" );
00638 }
00639 
00640 #include "exchangedownload.moc"
KDE Logo
This file is part of the documentation for libkpimexchange Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Apr 4 04:48:16 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003