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   mAccount = account;
00068   mDownloadsBusy = 0;
00069   mProgress = 0L;
00070   mCalendar = 0L;
00071   mFormat = new KCal::ICalFormat();
00072 }
00073 
00074 ExchangeDownload::~ExchangeDownload()
00075 {
00076   kdDebug() << "ExchangeDownload destructor" << endl;
00077   delete mFormat;
00078   if ( mEvents ) delete mEvents;
00079 }
00080 
00081 void ExchangeDownload::download(KCal::Calendar* calendar, const QDate& start, const QDate& end, bool showProgress)
00082 {
00083   mCalendar = calendar;
00084   mEvents = 0;
00085 
00086   if( showProgress ) {
00087     //kdDebug() << "Creating progress dialog" << endl;
00088     mProgress = new ExchangeProgress();
00089     mProgress->show();
00090   
00091     connect( this, SIGNAL(startDownload()), mProgress, SLOT(slotTransferStarted()) );
00092     connect( this, SIGNAL(finishDownload()), mProgress, SLOT(slotTransferFinished()) );
00093   }
00094 
00095   QString sql = dateSelectQuery( start, end.addDays( 1 ) );
00096  
00097   // kdDebug() << "Exchange download query: " << endl << sql << endl;
00098 
00099   increaseDownloads();
00100 
00101   KIO::DavJob *job = KIO::davSearch( mAccount->calendarURL(), "DAV:", "sql", sql, false );
00102   KIO::Scheduler::scheduleJob(job);
00103   job->setWindow( mWindow );
00104   connect(job, SIGNAL(result( KIO::Job * )), this, SLOT(slotSearchResult(KIO::Job *)));
00105 }
00106 
00107 void ExchangeDownload::download( const QDate& start, const QDate& end, bool showProgress )
00108 {
00109   mCalendar = 0;
00110   mEvents = new QPtrList<KCal::Event>;
00111 
00112   if( showProgress ) {
00113     //kdDebug() << "Creating progress dialog" << endl;
00114     mProgress = new ExchangeProgress();
00115     mProgress->show();
00116   
00117     connect( this, SIGNAL(startDownload()), mProgress, SLOT(slotTransferStarted()) );
00118     connect( this, SIGNAL(finishDownload()), mProgress, SLOT(slotTransferFinished()) );
00119   }
00120 
00121   QString sql = dateSelectQuery( start, end.addDays( 1 ) );
00122  
00123   increaseDownloads();
00124 
00125   KIO::DavJob *job = KIO::davSearch( mAccount->calendarURL(), "DAV:", "sql", sql, false );
00126   KIO::Scheduler::scheduleJob(job);
00127   job->setWindow( mWindow );
00128   connect(job, SIGNAL(result( KIO::Job * )), this, SLOT(slotSearchResult(KIO::Job *)));
00129 }
00130 
00131 QString ExchangeDownload::dateSelectQuery( const QDate& start, const QDate& end )
00132 {
00133   QString startString;
00134   startString.sprintf("%04i/%02i/%02i",start.year(),start.month(),start.day());
00135   QString endString;
00136   endString.sprintf("%04i/%02i/%02i",end.year(),end.month(),end.day());
00137   QString sql = 
00138         "SELECT \"DAV:href\", \"urn:schemas:calendar:instancetype\", \"urn:schemas:calendar:uid\"\r\n"
00139         "FROM Scope('shallow traversal of \"\"')\r\n"
00140         "WHERE \"urn:schemas:calendar:dtend\" > '" + startString + "'\r\n"
00141         "AND \"urn:schemas:calendar:dtstart\" < '" + endString + "'";
00142   return sql;
00143 }
00144 
00145 
00146 void ExchangeDownload::slotSearchResult( KIO::Job *job )
00147 {
00148   if ( job->error() ) {
00149     kdError() << "Error result for search: " << job->error() << endl;
00150     job->showErrorDialog( 0L );
00151     finishUp( ExchangeClient::CommunicationError, job );
00152     return;
00153   }
00154   QDomDocument& response = static_cast<KIO::DavJob *>( job )->response();
00155 
00156   // kdDebug() << "Search result: " << endl << response.toString() << endl;
00157 
00158   handleAppointments( response, true );
00159   
00160   decreaseDownloads();
00161 }
00162 
00163 void ExchangeDownload::slotMasterResult( KIO::Job *job )
00164 {
00165   if ( job->error() ) {
00166     kdError() << "Error result for Master search: " << job->error() << endl;
00167     job->showErrorDialog( 0L );
00168     finishUp( ExchangeClient::CommunicationError, job );
00169     return;
00170   }
00171   QDomDocument& response = static_cast<KIO::DavJob *>( job )->response();
00172 
00173   kdDebug() << "Search (master) result: " << endl << response.toString() << endl;
00174 
00175   handleAppointments( response, false );
00176   
00177   decreaseDownloads();
00178 }
00179 
00180 void ExchangeDownload::handleAppointments( const QDomDocument& response, bool recurrence ) {
00181   // kdDebug() << "Entering handleAppointments" << endl;
00182   int successCount = 0;
00183 
00184   if ( response.documentElement().firstChild().toElement().isNull() ) {
00185     // Got an empty response, but no error. This would mean there are
00186     // no appointments in this time period.
00187     return;
00188   }
00189 
00190   for( QDomElement item = response.documentElement().firstChild().toElement();
00191        !item.isNull();
00192        item = item.nextSibling().toElement() )
00193   {
00194     //kdDebug() << "Current item:" << item.tagName() << endl;
00195     QDomNodeList propstats = item.elementsByTagNameNS( "DAV:", "propstat" );
00196     // kdDebug() << "Item has " << propstats.count() << " propstat children" << endl; 
00197     for( uint i=0; i < propstats.count(); i++ )
00198     {
00199       QDomElement propstat = propstats.item(i).toElement();
00200       QDomElement prop = propstat.namedItem( "prop" ).toElement();
00201       if ( prop.isNull() )
00202       {
00203         kdError() << "Error: no <prop> in response" << endl;
00204     continue;
00205       }
00206 
00207       QDomElement instancetypeElement = prop.namedItem( "instancetype" ).toElement();
00208       if ( instancetypeElement.isNull() ) {
00209         kdError() << "Error: no instance type in Exchange server reply" << endl;
00210         continue;
00211       }
00212       int instanceType = instancetypeElement.text().toInt();
00213       //kdDebug() << "Instance type: " << instanceType << endl;
00214     
00215       if ( recurrence && instanceType > 0 ) {
00216         QDomElement uidElement = prop.namedItem( "uid" ).toElement();
00217         if ( uidElement.isNull() ) {
00218           kdError() << "Error: no uid in Exchange server reply" << endl;
00219           continue;
00220         }
00221         QString uid = uidElement.text();
00222         if ( ! m_uids.contains( uid ) ) {
00223           m_uids[uid] = 1;
00224           handleRecurrence(uid);
00225           successCount++;
00226         }
00227         continue;
00228       }
00229 
00230       QDomElement hrefElement = prop.namedItem( "href" ).toElement();
00231       if ( hrefElement.isNull() ) {
00232         kdError() << "Error: no href in Exchange server reply" << endl;
00233         continue;
00234       }
00235       QString href = hrefElement.text();
00236       KURL url(href);
00237       
00238       kdDebug() << "Getting appointment from url: " << url.prettyURL() << endl;
00239       
00240       readAppointment( toDAV( url ) );
00241       successCount++;
00242     }
00243   }
00244   if ( !successCount ) {
00245     finishUp( ExchangeClient::ServerResponseError, "WebDAV SEARCH response:\n" + response.toString() );
00246   }
00247 }  
00248 
00249 void ExchangeDownload::handleRecurrence(QString uid) {
00250   // kdDebug() << "Handling recurrence info for uid=" << uid << endl;
00251   QString query = 
00252         "SELECT \"DAV:href\", \"urn:schemas:calendar:instancetype\"\r\n"
00253         "FROM Scope('shallow traversal of \"\"')\r\n"
00254         "WHERE \"urn:schemas:calendar:uid\" = '" + uid + "'\r\n"
00255     " AND (\"urn:schemas:calendar:instancetype\" = 1)\r\n";
00256 //  "      OR \"urn:schemas:calendar:instancetype\" = 3)\r\n" // FIXME: exception are not handled
00257 
00258   // kdDebug() << "Exchange master query: " << endl << query << endl;
00259 
00260   increaseDownloads();
00261  
00262   KIO::DavJob* job = KIO::davSearch( mAccount->calendarURL(), "DAV:", "sql", query, false );
00263   KIO::Scheduler::scheduleJob(job);
00264   job->setWindow( mWindow );
00265   connect(job, SIGNAL(result( KIO::Job * )), this, SLOT(slotMasterResult(KIO::Job *)));
00266 }
00267 
00268 void ExchangeDownload::readAppointment( const KURL& url )
00269 {
00270   QDomDocument doc;
00271   QDomElement root = addElement( doc, doc, "DAV:", "propfind" );
00272   QDomElement prop = addElement( doc, root, "DAV:", "prop" );
00273   addElement( doc, prop, "urn:schemas:calendar:", "uid" );
00274   addElement( doc, prop, "urn:schemas:calendar:", "timezoneid" );
00275   addElement( doc, prop, "urn:schemas:calendar:", "timezone" );
00276   addElement( doc, prop, "urn:schemas:calendar:", "lastmodified" );
00277   addElement( doc, prop, "urn:schemas:calendar:", "organizer" );
00278   addElement( doc, prop, "urn:schemas:calendar:", "contact" );
00279   addElement( doc, prop, "urn:schemas:httpmail:", "to" );
00280   addElement( doc, prop, "urn:schemas:calendar:", "attendeestatus" );
00281   addElement( doc, prop, "urn:schemas:calendar:", "attendeerole" );
00282   addElement( doc, prop, "DAV:", "isreadonly" );
00283   addElement( doc, prop, "urn:schemas:calendar:", "instancetype" );
00284   addElement( doc, prop, "urn:schemas:calendar:", "created" );
00285   addElement( doc, prop, "urn:schemas:calendar:", "dtstart" );
00286   addElement( doc, prop, "urn:schemas:calendar:", "dtend" );
00287   addElement( doc, prop, "urn:schemas:calendar:", "alldayevent" );
00288   addElement( doc, prop, "urn:schemas:calendar:", "transparent" );
00289   addElement( doc, prop, "urn:schemas:httpmail:", "textdescription" );
00290   addElement( doc, prop, "urn:schemas:httpmail:", "subject" );
00291   addElement( doc, prop, "urn:schemas:calendar:", "location" );
00292   addElement( doc, prop, "urn:schemas:calendar:", "rrule" );
00293   addElement( doc, prop, "urn:schemas:calendar:", "exdate" );
00294   addElement( doc, prop, "urn:schemas:mailheader:", "sensitivity" );
00295   addElement( doc, prop, "urn:schemas:calendar:", "reminderoffset" );
00296   
00297   addElement( doc, prop, "urn:schemas-microsoft-com:office:office", "Keywords" );
00298 
00299 //  addElement( doc, prop, "", "" );
00300 //  addElement( doc, prop, "DAV:", "" );
00301 //  addElement( doc, prop, "urn:schemas:calendar:", "" );
00302 //  addElement( doc, prop, "urn:content-classes:appointment", "" );
00303 //  addElement( doc, prop, "urn:schemas:httpmail:", "" );
00304 
00305   increaseDownloads();
00306 
00307   KIO::DavJob* job = KIO::davPropFind( url, doc, "0", false );
00308   KIO::Scheduler::scheduleJob(job);
00309   job->setWindow( mWindow );
00310   job->addMetaData( "errorPage", "false" );
00311   connect( job, SIGNAL( result( KIO::Job * ) ), this, SLOT( slotPropFindResult( KIO::Job * ) ) );
00312 }
00313 
00314 void ExchangeDownload::slotPropFindResult( KIO::Job * job )
00315 {
00316   // kdDebug() << "slotPropFindResult" << endl;
00317 
00318   int error = job->error(); 
00319   if ( error )
00320   {
00321     job->showErrorDialog( 0L );
00322     finishUp( ExchangeClient::CommunicationError, job );
00323     return;
00324   }
00325 
00326   QDomDocument response = static_cast<KIO::DavJob *>( job )->response();
00327 //  kdDebug() << "Response: " << endl;
00328 //  kdDebug() << response.toString() << endl;
00329 
00330   QDomElement prop = response.documentElement().namedItem( "response" ).namedItem( "propstat" ).namedItem( "prop" ).toElement();
00331  
00332   KCal::Event* event = new KCal::Event();
00333 
00334   QDomElement uidElement = prop.namedItem( "uid" ).toElement();
00335   if ( uidElement.isNull() ) {
00336     kdError() << "Error: no uid in Exchange server reply" << endl;
00337     finishUp( ExchangeClient::IllegalAppointmentError, "WebDAV server response:\n" + response.toString() );
00338     return;
00339   }
00340   event->setUid( uidElement.text() );
00341   // kdDebug() << "Got UID: " << uidElement.text() << endl;
00342 
00343   QString timezoneid = prop.namedItem( "timezoneid" ).toElement().text();
00344   // kdDebug() << "DEBUG: timezoneid = " << timezoneid << endl;
00345 
00346   QString timezone = prop.namedItem( "timezone" ).toElement().text();
00347   // kdDebug() << "DEBUG: timezone = " << timezone << endl;
00348 
00349   // mFormat is used for parsing recurrence rules.
00350   QString localTimeZoneId;
00351   if ( mCalendar ) {
00352     mFormat->setTimeZone( mCalendar->timeZoneId(), !mCalendar->isLocalTime() );
00353     localTimeZoneId = mCalendar->timeZoneId();
00354   }  else {
00355     localTimeZoneId = "UTC";
00356     // If no mCalendar, stay in UTC
00357   }
00358 
00359   QString lastModified = prop.namedItem( "lastmodified" ).toElement().text();
00360   QDateTime dt = utcAsZone( QDateTime::fromString( lastModified, Qt::ISODate ), localTimeZoneId );
00361   event->setLastModified( dt );
00362   // kdDebug() << "Got lastModified:" << lastModified << ", " << dt.toString() << endl;
00363 
00364   QString organizer = prop.namedItem( "organizer" ).toElement().text();
00365   event->setOrganizer( organizer );
00366   // kdDebug() << "Got organizer: " << organizer << endl;
00367 
00368   // Trying to find attendees, not working yet
00369   QString contact = prop.namedItem( "contact" ).toElement().text();
00370 //  event->setOrganizer( organizer );
00371   // kdDebug() << "DEBUG: Got contact: " << contact << endl;
00372 
00373   // This looks promising for finding attendees
00374   // FIXME: get this to work
00375   QString to = prop.namedItem( "to" ).toElement().text();
00376   // kdDebug() << "DEBUG: Got to: " << to << endl;
00377   QStringList attn = QStringList::split( ",", to ); // This doesn't work: there can be commas between ""
00378   QStringList::iterator it;
00379   for ( it = attn.begin(); it != attn.end(); ++it ) {
00380     // kdDebug() << "    attendee: " << (*it) << endl;
00381     QString name = "";
00382     // KCal::Attendee* a = new KCal::Attendee( name, email );
00383 
00384     // event->addAttendee( a );
00385   }
00386 
00387   QString readonly = prop.namedItem( "isreadonly" ).toElement().text();
00388   event->setReadOnly( readonly != "0" );
00389   // kdDebug() << "Got readonly: " << readonly << ":" << (readonly != "0") << endl;
00390 
00391   QString created = prop.namedItem( "created" ).toElement().text();
00392   dt = utcAsZone( QDateTime::fromString( created, Qt::ISODate ), localTimeZoneId );
00393   event->setCreated( dt );
00394   // kdDebug() << "got created: " << dt.toString() << endl;
00395 
00396   QString dtstart = prop.namedItem( "dtstart" ).toElement().text();
00397   dt = utcAsZone( QDateTime::fromString( dtstart, Qt::ISODate ), localTimeZoneId );
00398   event->setDtStart( dt );
00399   // kdDebug() << "got dtstart: " << dtstart << " becomes in timezone " << dt.toString() << endl;
00400 
00401   QString alldayevent = prop.namedItem( "alldayevent" ).toElement().text();
00402   bool floats = alldayevent.toInt() != 0;
00403   event->setFloats( floats );
00404   // kdDebug() << "Got alldayevent: \"" << alldayevent << "\":" << floats << endl;
00405 
00406   QString dtend = prop.namedItem( "dtend" ).toElement().text();
00407   dt = utcAsZone( QDateTime::fromString( dtend, Qt::ISODate ), localTimeZoneId );
00408   // Outlook thinks differently about floating event timing than libkcal
00409   if ( floats ) dt = dt.addDays( -1 );
00410   event->setDtEnd( dt );
00411   // kdDebug() << "got dtstart: " << dtend << " becomes in timezone " << dt.toString() << endl;
00412 
00413   QString transparent = prop.namedItem( "transparent" ).toElement().text();
00414   event->setTransparency( transparent.toInt() > 0 ? KCal::Event::Transparent
00415               : KCal::Event::Opaque );
00416   // kdDebug() << "Got transparent: " << transparent << endl;
00417 
00418   QString description = prop.namedItem( "textdescription" ).toElement().text();
00419   event->setDescription( description );
00420   // kdDebug() << "Got description: " << description << endl;
00421 
00422   QString subject = prop.namedItem( "subject" ).toElement().text();
00423   event->setSummary( subject );
00424   // kdDebug() << "Got summary: " << subject << endl;
00425 
00426   QString location =  prop.namedItem( "location" ).toElement().text();
00427   event->setLocation( location );
00428   // kdDebug() << "Got location: " << location << endl;
00429 
00430   QString rrule = prop.namedItem( "rrule" ).toElement().text();
00431   // kdDebug() << "Got rrule: " << rrule << endl;
00432   if ( ! rrule.isNull() ) {
00433     // Timezone should be handled automatically 
00434     // because we used mFormat->setTimeZone() earlier
00435     if ( ! mFormat->fromString( event->recurrence(), rrule ) ) {
00436       kdError() << "ERROR parsing rrule " << rrule << endl;
00437     }
00438   }
00439 
00440   QDomElement keywords = prop.namedItem( "Keywords" ).toElement();
00441   QStringList categories;
00442   QDomNodeList list = keywords.elementsByTagNameNS( "xml:", "v" );
00443   for( uint i=0; i < list.count(); i++ ) {
00444     QDomElement item = list.item(i).toElement();
00445     categories.append( item.text() );
00446   }
00447   event->setCategories( categories );
00448   // kdDebug() << "Got categories: " << categories.join( ", " ) << endl;
00449 
00450 
00451   QDomElement exdate = prop.namedItem( "exdate" ).toElement();
00452   KCal::DateList exdates;
00453   list = exdate.elementsByTagNameNS( "xml:", "v" );
00454   for( uint i=0; i < list.count(); i++ ) {
00455     QDomElement item = list.item(i).toElement();
00456     QDate date = utcAsZone( QDateTime::fromString( item.text(), Qt::ISODate ), localTimeZoneId ).date();
00457     exdates.append( date );
00458     // kdDebug() << "Got exdate: " << date.toString() << endl;
00459   }
00460   event->setExDates( exdates );
00461 
00462   // Exchange sentitivity values:
00463   // 0 None
00464   // 1 Personal
00465   // 2 Private
00466   // 3 Company Confidential
00467   QString sensitivity = prop.namedItem( "sensitivity" ).toElement().text();
00468   if ( ! sensitivity.isNull() ) 
00469   switch( sensitivity.toInt() ) {
00470     case 0: event->setSecrecy( KCal::Incidence::SecrecyPublic ); break;
00471     case 1: event->setSecrecy( KCal::Incidence::SecrecyPrivate ); break;
00472     case 2: event->setSecrecy( KCal::Incidence::SecrecyPrivate ); break;
00473     case 3: event->setSecrecy( KCal::Incidence::SecrecyConfidential ); break;
00474     default: kdWarning() << "Unknown sensitivity: " << sensitivity << endl;
00475   }
00476   // kdDebug() << "Got sensitivity: " << sensitivity << endl;
00477 
00478 
00479   QString reminder = prop.namedItem( "reminderoffset" ).toElement().text();
00480   // kdDebug() << "Reminder offset: " << reminder << endl;
00481   if ( ! reminder.isNull() ) {
00482     // Duration before event in seconds
00483     KCal::Duration offset( - reminder.toInt() );
00484     KCal::Alarm* alarm = event->newAlarm();
00485     alarm->setStartOffset( offset );
00486     alarm->setEnabled( true );
00487     // TODO: multiple alarms; alarm->setType( KCal::Alarm::xxxx );
00488   }
00490     //Alarm* newAlarm();
00492     //void addAlarm(Alarm*);
00493 
00495     //void setRelatedTo(Incidence *relatedTo);
00497     //void addRelation(Incidence *);
00498 
00500     //void setAttachments(const QStringList &attachments);
00501  
00503     //void setResources(const QStringList &resources);
00504 
00506     //void setPriority(int priority);
00507 
00513     //void addAttendee(Attendee *a, bool doupdate=true );
00514 
00515   // THE FOLLOWING EVENT PROPERTIES ARE NOT READ
00516 
00517   // Revision ID in webdav is a String, not an int
00519     //void setRevision(int rev);
00520 
00521   // Problem: When you sync Outlook to a Palm, the conduit splits up
00522   // multi-day events into single-day events WITH ALL THE SAME UID
00523   // Grrrrrrr.
00524   if ( mCalendar ) {
00525     KCal::Event* oldEvent = mCalendar->event( event->uid() );
00526     if ( oldEvent ) {
00527       kdWarning() << "Already got his event, keeping old version..." << endl;
00528       // This doesn't work
00529       // *oldEvent = *event;
00530     } else {
00531       mCalendar->addEvent( event );
00532     }
00533   } else {
00534     emit gotEvent( event, static_cast<KIO::DavJob *>( job )->url() );
00535 //    mEvents->append( event );
00536   }
00537 
00538   decreaseDownloads();
00539 }
00540 
00541 void ExchangeDownload::increaseDownloads()
00542 {
00543   mDownloadsBusy++;
00544   emit startDownload();
00545 }
00546 
00547 void ExchangeDownload::decreaseDownloads()
00548 {
00549   mDownloadsBusy--;
00550   // kdDebug() << "Download finished, waiting for " << mDownloadsBusy << " more" << endl;
00551   emit finishDownload();
00552   if ( mDownloadsBusy == 0 ) {
00553     kdDebug() << "All downloads finished" << endl;
00554     finishUp( ExchangeClient::ResultOK );
00555   }
00556 }
00557 
00558 void ExchangeDownload::finishUp( int result, const QString& moreInfo )
00559 {
00560   if ( mCalendar ) mCalendar->setModified( true );
00561   // Disconnect from progress bar
00562   if ( mProgress ) {
00563     disconnect( this, 0, mProgress, 0 );
00564     disconnect( mProgress, 0, this, 0 );
00565     mProgress->delayedDestruct();
00566   }
00567 
00568 //  if ( mEvents ) {
00569 //    emit finished( this, result, moreInfo, *mEvents );
00570 //  } else {
00571     emit finished( this, result, moreInfo );
00572 //  }
00573 }
00574 
00575 void ExchangeDownload::finishUp( int result, KIO::Job* job )
00576 {
00577   finishUp( result, QString("WebDAV job error code = ") + QString::number( job->error() ) + ";\n" + "\"" + job->errorString() + "\"" );
00578 }
00579 
00580 #include "exchangedownload.moc"
KDE Logo
This file is part of the documentation for libkpimexchange Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:38:09 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003