libkpimexchange Library API Documentation

resourceexchange.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 modify it
00006     under the terms of the GNU Library General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or (at your
00008     option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful, but WITHOUT
00011     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013     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 the
00017     Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00018     02111-1307, USA.
00019 */
00020 
00021 #include <stdlib.h>
00022 
00023 #include <qdatetime.h>
00024 #include <qstring.h>
00025 #include <qptrlist.h>
00026 #include <qwidgetlist.h>
00027 #include <qwidget.h>
00028 
00029 #include <kdebug.h>
00030 #include <kapplication.h>
00031 #include <kstringhandler.h>
00032 
00033 #include <libkcal/calendarlocal.h>
00034 #include <libkcal/calendar.h>
00035 #include <libkcal/journal.h>
00036 
00037 #include <kresources/configwidget.h>
00038 
00039 #include <kabc/locknull.h>
00040 
00041 #include "dateset.h"
00042 #include "exchangeaccount.h"
00043 #include "exchangeclient.h"
00044 #include "exchangemonitor.h"
00045 
00046 #include "resourceexchange.h"
00047 #include "resourceexchangeconfig.h"
00048 
00049 using namespace KCal;
00050 using namespace KPIM;
00051 
00052 extern "C"
00053 {
00054   void* init_resourcecalendarexchange()
00055   {
00056     return new KRES::PluginFactory<ResourceExchange,ResourceExchangeConfig>();
00057   }
00058 }
00059 
00060 class ResourceExchange::EventInfo {
00061 public:
00062   KCal::Event* event;
00063   KURL url;
00064   long updateWatch;
00065 };
00066 
00067 ResourceExchange::ResourceExchange( const KConfig *config )
00068   : ResourceCalendar( config )
00069 {
00070   mLock = new KABC::LockNull( true );
00071 
00072   mCache = 0;
00073   mTimeZoneId = QString::fromLatin1( "UTC" );
00074 
00075   kdDebug() << "Creating ResourceExchange" << endl;
00076   if (config ) {
00077     mAccount = new ExchangeAccount(
00078             config->readEntry( "ExchangeHost" ),
00079             config->readEntry( "ExchangePort" ),
00080             config->readEntry( "ExchangeAccount" ),
00081             KStringHandler::obscure( config->readEntry( "ExchangePassword" ) ),
00082             config->readEntry( "ExchangeMailbox" ) );
00083     mCachedSeconds = config->readNumEntry( "ExchangeCacheTimeout", 600 );
00084     mAutoMailbox = config->readBoolEntry( "ExchangeAutoMailbox", true );
00085   } else {
00086     mAccount = new ExchangeAccount( "", "", "", "" );
00087     mCachedSeconds = 600;
00088   }
00089 }
00090 
00091 ResourceExchange::~ResourceExchange()
00092 {
00093   kdDebug() << "Destructing ResourceExchange" << endl;
00094   close();
00095 }
00096 
00097 void ResourceExchange::writeConfig( KConfig* config )
00098 {
00099   ResourceCalendar::writeConfig( config );
00100   config->writeEntry( "ExchangeHost", mAccount->host() );
00101   config->writeEntry( "ExchangePort", mAccount->port() );
00102   config->writeEntry( "ExchangeAccount", mAccount->account() );
00103   config->writeEntry( "ExchangeMailbox", mAccount->mailbox() );
00104   config->writeEntry( "ExchangePassword", KStringHandler::obscure( mAccount->password() ) );
00105   config->writeEntry( "ExchangeCacheTimeout", mCachedSeconds );
00106   config->writeEntry( "ExchangeAutoMailbox", mAutoMailbox );
00107 }
00108 
00109 bool ResourceExchange::doOpen()
00110 {
00111   mClient = new ExchangeClient( mAccount );
00112   connect( mClient, SIGNAL( downloadFinished( int, const QString& ) ),
00113     this, SLOT( slotDownloadFinished( int, const QString& ) ) );
00114   connect( mClient, SIGNAL( event( KCal::Event*, const KURL& ) ),
00115     this, SLOT( downloadedEvent( KCal::Event*, const KURL& ) ) );
00116 
00117   kdDebug() << "Creating monitor" << endl;
00118   QHostAddress ip;
00119   ip.setAddress( mAccount->host() );
00120   mMonitor = new ExchangeMonitor( mAccount, ExchangeMonitor::CallBack, ip );
00121   connect( mMonitor, SIGNAL(notify( const QValueList<long>& , const QValueList<KURL>& )), this, SLOT(slotMonitorNotify( const QValueList<long>& , const QValueList<KURL>& )) );
00122   connect( mMonitor, SIGNAL(error(int , const QString&)), this, SLOT(slotMonitorError(int , const QString&)) );
00123 
00124   mMonitor->addWatch( mAccount->calendarURL(), ExchangeMonitor::UpdateNewMember, 1 );
00125 
00126   QWidgetList* widgets = QApplication::topLevelWidgets();
00127   if ( !widgets->isEmpty() )
00128     mClient->setWindow( widgets->first() );
00129   delete widgets;
00130 
00131   mDates = new DateSet();
00132 
00133   mEventDates = new QMap<Event,QDateTime>();
00134   mCacheDates = new QMap<QDate, QDateTime>();
00135 
00136   mCache = new CalendarLocal( mTimeZoneId );
00137   // mOldestDate = 0L;
00138   // mNewestDate = 0L;
00139 
00140   // FIXME: check if server exists, account is OK, etc.
00141   return true;
00142 }
00143 
00144 void ResourceExchange::doClose()
00145 {
00146   kdDebug() << "ResourceExchange::doClose()" << endl;
00147   // delete mNewestDate;
00148   // delete mOldestDate;
00149   delete mDates; mDates = 0;
00150   delete mMonitor; mMonitor = 0;
00151   delete mClient; mClient = 0;
00152   delete mAccount; mAccount = 0;
00153   delete mEventDates; mEventDates = 0;
00154   delete mCacheDates; mCacheDates = 0;
00155   if (mCache) {
00156     mCache->close();
00157     delete mCache; mCache = 0;
00158   }
00159 //  setModified( false );
00160 }
00161 
00162 bool ResourceExchange::load()
00163 {
00164   return true;
00165 }
00166 
00167 bool ResourceExchange::save()
00168 {
00169   return true;
00170 }
00171 
00172 KABC::Lock *ResourceExchange::lock()
00173 {
00174   return mLock;
00175 }
00176 
00177 void ResourceExchange::slotMonitorNotify( const QValueList<long>& IDs, const QValueList<KURL>& urls )
00178 {
00179   kdDebug() << "ResourceExchange::slotMonitorNotify()" << endl;
00180 
00181   QString result;
00182   KPIM::ExchangeMonitor::IDList::ConstIterator it;
00183   for ( it = IDs.begin(); it != IDs.end(); ++it ) {
00184     if ( it == IDs.begin() )
00185       result += QString::number( (*it) );
00186     else
00187       result += "," + QString::number( (*it) );
00188   }
00189   kdDebug() << "Got signals for " << result << endl;
00190   QValueList<KURL>::ConstIterator it2;
00191   for ( it2 = urls.begin(); it2 != urls.end(); ++it2 ) {
00192     kdDebug() << "URL: " << (*it2).prettyURL() << endl;
00193   }
00194 
00195   /* Now find out what happened:
00196    * One or more of the following:
00197    * 1. Event added in period that we think we have cached
00198    * 2. Event deleted that we have in cache
00199    * 3. Event modified that we have in cache
00200    * 4. Something else happened that isn't relevant to us
00201    * Update cache, then notify whoever's watching us
00202    * We may be able to find (1) and (3) by looking at the
00203    *   DAV:getlastmodified property
00204    * (2) is trickier: we might have to resort to checking
00205    * all uids in the cache
00206    * Or: put monitors on every event in the cache, so that
00207    * we know when one gets deleted or modified
00208    * Only look for new events using the global monitor
00209    */
00210 }
00211 
00212 void ResourceExchange::slotMonitorError( int errorCode, const QString& moreInfo )
00213 {
00214   kdError() << "Ignoring error from Exchange monitor, code=" << errorCode << "; more info: " << moreInfo << endl;
00215 }
00216 
00217 
00218 bool ResourceExchange::addEvent(Event *anEvent)
00219 {
00220     if( !mCache )
00221         return false;
00222   kdDebug() << "ResourceExchange::addEvent" << endl;
00223 
00224   // FIXME: first check of upload finished successfully, only then
00225   // add to cache
00226   mCache->addEvent( anEvent );
00227 
00228   uploadEvent( anEvent );
00229 //  insertEvent(anEvent);
00230 
00231   anEvent->registerObserver( this );
00232 //  setModified( true );
00233 
00234   return true;
00235 }
00236 
00237 void ResourceExchange::uploadEvent( Event* event )
00238 {
00239   mClient->uploadSynchronous( event );
00240 }
00241 
00242 void ResourceExchange::deleteEvent(Event *event)
00243 {
00244     if ( !mCache )
00245         return;
00246   kdDebug(5800) << "ResourceExchange::deleteEvent" << endl;
00247 
00248   mClient->removeSynchronous( event );
00249 
00250   // This also frees the event
00251   mCache->deleteEvent( event );
00252 
00253 //  setModified( true );
00254 }
00255 
00256 
00257 Event *ResourceExchange::event( const QString &uid )
00258 {
00259   kdDebug(5800) << "ResourceExchange::event(): " << uid << endl;
00260 
00261   // FIXME: Look in exchange server for uid!
00262   return mCache->event( uid );
00263 }
00264 
00265 void ResourceExchange::subscribeEvents( const QDate& start, const QDate& end )
00266 {
00267   kdDebug(5800) << "ResourceExchange::subscribeEvents()" << endl;
00268   // FIXME: possible race condition if several subscribe events are run close
00269   // to each other
00270   mClient->download( start, end, false );
00271 }
00272 
00273 void ResourceExchange::downloadedEvent( KCal::Event* event, const KURL& url )
00274 {
00275   kdDebug() << "Downloaded event: " << event->summary() << " from url " << url.prettyURL() << endl;
00276     // FIXME: add watches to the monitor for these events
00277     // KURL url =
00278     //  mMonitor->addWatch( url, KPIM::ExchangeMonitor::Update, 0 );
00279 //    emit eventsAdded( events );
00280 }
00281 
00282 void ResourceExchange::slotDownloadFinished( int result, const QString& moreinfo )
00283 {
00284   kdDebug() << "ResourceExchange::downloadFinished" << endl;
00285 
00286   if ( result != KPIM::ExchangeClient::ResultOK ) {
00287     // Do something useful with the error report
00288     kdError() << "ResourceExchange::slotDownloadFinished(): error " << result << ": " << moreinfo << endl;
00289   }
00290 }
00291 
00292 void ResourceExchange::unsubscribeEvents( const QDate& start, const QDate& end )
00293 {
00294   kdDebug() << "ResourceExchange::unsubscribeEvents()" << endl;
00295 }
00296 
00297 bool ResourceExchange::addTodo(Todo *todo)
00298 {
00299     if( !mCache)
00300         return false;
00301   mCache->addTodo( todo );
00302 
00303   todo->registerObserver( this );
00304 
00305 //  setModified( true );
00306 
00307   return true;
00308 }
00309 
00310 void ResourceExchange::deleteTodo(Todo *todo)
00311 {
00312     if( !mCache )
00313         return;
00314   mCache->deleteTodo( todo );
00315 
00316 //  setModified( true );
00317 }
00318 
00319 Todo::List ResourceExchange::rawTodos()
00320 {
00321   return mCache->rawTodos();
00322 }
00323 
00324 Todo *ResourceExchange::todo( const QString &uid )
00325 {
00326   return mCache->todo( uid );
00327 }
00328 
00329 Todo::List ResourceExchange::todos( const QDate &date )
00330 {
00331   return mCache->todos( date );
00332 }
00333 
00334 Alarm::List ResourceExchange::alarmsTo( const QDateTime &to )
00335 {
00336   return mCache->alarmsTo( to );
00337 }
00338 
00339 Alarm::List ResourceExchange::alarms( const QDateTime &from, const QDateTime &to )
00340 {
00341   kdDebug(5800) << "ResourceExchange::alarms(" << from.toString() << " - " << to.toString() << ")\n";
00342   return mCache->alarms( from, to );
00343 }
00344 
00345 /****************************** PROTECTED METHODS ****************************/
00346 
00347 // after changes are made to an event, this should be called.
00348 void ResourceExchange::update(IncidenceBase *incidence)
00349 {
00350   Event* event = dynamic_cast<Event *>( incidence );
00351   if ( event ) {
00352     kdDebug() << "Event updated, resubmit to server..." << endl;
00353     uploadEvent( event );
00354   }
00355 //  setModified( true );
00356 }
00357 
00358 // this function will take a VEvent and insert it into the event
00359 // dictionary for the ResourceExchange.  If there is no list of events for that
00360 // particular location in the dictionary, a new one will be created.
00361 /*
00362 void ResourceExchange::insertEvent(const Event *anEvent)
00363 {
00364   kdDebug() << "ResourceExchange::insertEvent" << endl;
00365 
00366 }
00367 */
00368 // taking a QDate, this function will look for an eventlist in the dict
00369 // with that date attached -
00370 Event::List ResourceExchange::rawEventsForDate(const QDate &qd, bool sorted)
00371 {
00372   // kdDebug() << "ResourceExchange::rawEventsForDate(" << qd.toString() << "," << sorted << ")" << endl;
00373 
00374   // If the events for this date are not in the cache, or if they are old,
00375   // get them again
00376   QDateTime now = QDateTime::currentDateTime();
00377   // kdDebug() << "Now is " << now.toString() << endl;
00378   // kdDebug() << "mDates: " << mDates << endl;
00379   // kdDebug() << "mDates->contains(qd) is " << mDates->contains( qd ) << endl;
00380   QDate start = QDate( qd.year(), qd.month(), 1 ); // First day of month
00381   if ( !mDates->contains( start ) || (*mCacheDates)[start].secsTo( now ) > mCachedSeconds ) {
00382     QDate end = start.addMonths( 1 ).addDays( -1 ); // Last day of month
00383     // Get events that occur in this period from the cache
00384     Event::List oldEvents = mCache->rawEvents( start, end, false );
00385     // And remove them all
00386     Event::List::ConstIterator it;
00387     for( it = oldEvents.begin(); it != oldEvents.end(); ++it ) {
00388       mCache->deleteEvent( *it );
00389     }
00390 
00391     kdDebug() << "Reading events for month of " << start.toString() << endl;
00392     mClient->downloadSynchronous( mCache, start, end, true ); // Show progress dialog
00393     mDates->add( start );
00394     mCacheDates->insert( start, now );
00395   }
00396 
00397   // Events are safely in the cache now, return them from cache
00398   Event::List events = mCache->rawEventsForDate( qd, sorted );
00399   // kdDebug() << "Found " << events.count() << " events." << endl;
00400   return events;
00401 
00402 /*
00403   if (!sorted) {
00404     return eventList;
00405   }
00406 
00407   //  kdDebug(5800) << "Sorting events for date\n" << endl;
00408   // now, we have to sort it based on getDtStart.time()
00409   Event::List eventListSorted;
00410   for (anEvent = eventList.first(); anEvent; anEvent = eventList.next()) {
00411     if (!eventListSorted.isEmpty() &&
00412     anEvent->dtStart().time() < eventListSorted.at(0)->dtStart().time()) {
00413       eventListSorted.insert(0,anEvent);
00414       goto nextToInsert;
00415     }
00416     for (i = 0; (uint) i+1 < eventListSorted.count(); i++) {
00417       if (anEvent->dtStart().time() > eventListSorted.at(i)->dtStart().time() &&
00418       anEvent->dtStart().time() <= eventListSorted.at(i+1)->dtStart().time()) {
00419     eventListSorted.insert(i+1,anEvent);
00420     goto nextToInsert;
00421       }
00422     }
00423     eventListSorted.append(anEvent);
00424   nextToInsert:
00425     continue;
00426   }
00427   return eventListSorted;
00428 */
00429 }
00430 
00431 
00432 Event::List ResourceExchange::rawEvents( const QDate &start, const QDate &end,
00433                                           bool inclusive )
00434 {
00435    kdDebug() << "ResourceExchange::rawEvents(start,end,inclusive)" << endl;
00436  return mCache->rawEvents( start, end, inclusive );
00437 }
00438 
00439 Event::List ResourceExchange::rawEventsForDate(const QDateTime &qdt)
00440 {
00441    kdDebug() << "ResourceExchange::rawEventsForDate(qdt)" << endl;
00442  return rawEventsForDate( qdt.date() );
00443 }
00444 
00445 Event::List ResourceExchange::rawEvents()
00446 {
00447    kdDebug() << "ResourceExchange::rawEvents()" << endl;
00448  return mCache->rawEvents();
00449 }
00450 
00451 bool ResourceExchange::addJournal(Journal *journal)
00452 {
00453   kdDebug(5800) << "Adding Journal on " << journal->dtStart().toString() << endl;
00454   mCache->addJournal( journal );
00455 
00456   journal->registerObserver( this );
00457 
00458 //  setModified( true );
00459 
00460   return true;
00461 }
00462 
00463 void ResourceExchange::deleteJournal(Journal *journal)
00464 {
00465     if( !mCache )
00466         return;
00467   mCache->deleteJournal( journal );
00468 
00469 //  setModified( true );
00470 }
00471 
00472 Journal *ResourceExchange::journal(const QDate &date)
00473 {
00474     if( !mCache)
00475         return 0;
00476 //  kdDebug(5800) << "ResourceExchange::journal() " << date.toString() << endl;
00477     return mCache->journal( date );
00478 }
00479 
00480 Journal *ResourceExchange::journal(const QString &uid)
00481 {
00482     if( !mCache )
00483         return 0;
00484     return mCache->journal( uid );
00485 }
00486 
00487 Journal::List ResourceExchange::journals()
00488 {
00489   return mCache->journals();
00490 }
00491 
00492 void ResourceExchange::setTimeZoneId( const QString &tzid )
00493 {
00494   mTimeZoneId = tzid;
00495   if ( mCache ) mCache->setTimeZoneId( tzid );
00496 }
00497 #include "resourceexchange.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:10 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003