libkcal Library API Documentation

resourceimap.cpp

00001 /*
00002     This file is part of libkcal.
00003 
00004     Copyright (c) 2003 Steffen Hansen <steffen@klaralvdalens-datakonsult.se>
00005     Copyright (c) 2003 - 2004 Bo Thorsen <bo@klaralvdalens-datakonsult.se>
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Library General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Library General Public License for more details.
00016 
00017     You should have received a copy of the GNU Library General Public License
00018     along with this library; see the file COPYING.LIB.  If not, write to
00019     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00020     Boston, MA 02111-1307, USA.
00021 */
00022 
00023 #include <kdebug.h>
00024 #include <dcopclient.h>
00025 #include <kapplication.h>
00026 #include <kdcopservicestarter.h>
00027 #include <klocale.h>
00028 
00029 #include <libkcal/vcaldrag.h>
00030 #include <libkcal/vcalformat.h>
00031 #include <libkcal/exceptions.h>
00032 #include <libkcal/incidence.h>
00033 #include <libkcal/event.h>
00034 #include <libkcal/todo.h>
00035 #include <libkcal/journal.h>
00036 
00037 #include <kabc/locknull.h>
00038 
00039 #include <kresources/configwidget.h>
00040 #include <kresources/resource.h>
00041 
00042 #include "kmailicalIface_stub.h"
00043 
00044 
00045 #include "resourceimapconfig.h"
00046 #include "resourceimap.h"
00047 
00048 using namespace KCal;
00049 
00050 static const QCString dcopObjectId = "KMailICalIface";
00051 
00052 extern "C"
00053 {
00054   void *init_kcal_imap()
00055   {
00056     return new KRES::PluginFactory<ResourceIMAP,ResourceIMAPConfig>();
00057   }
00058 }
00059 
00060 
00061 ResourceIMAP::ResourceIMAP( const KConfig* config )
00062   : DCOPObject("ResourceIMAP"), ResourceCalendar( config )
00063 {
00064   if ( config ) {
00065     mServer = config->readEntry( "Servername" );
00066   }
00067   init();
00068 
00069   // Make the connection to KMail ready
00070   mKMailIcalIfaceStub = 0;
00071   kapp->dcopClient()->setNotifications( true );
00072   connect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString& ) ),
00073            this, SLOT( unregisteredFromDCOP( const QCString& ) ) );
00074 }
00075 
00076 void ResourceIMAP::writeConfig( KConfig* config )
00077 {
00078   ResourceCalendar::writeConfig( config );
00079   config->writeEntry( "Servername", mServer );
00080 }
00081 
00082 void ResourceIMAP::init()
00083 {
00084   mSilent = false;
00085 
00086   mDCOPClient = new DCOPClient();
00087   mDCOPClient->attach();
00088   mDCOPClient->registerAs( "resourceimap", true );
00089 }
00090 
00091 
00092 ResourceIMAP::~ResourceIMAP()
00093 {
00094   kapp->dcopClient()->setNotifications( false );
00095   delete mKMailIcalIfaceStub;
00096   close();
00097   delete mDCOPClient;
00098 }
00099 
00100 bool ResourceIMAP::getIncidenceList( QStringList& lst, const QString& type )
00101 {
00102   if ( !connectToKMail() ) {
00103     kdError() << "DCOP error during incidences(QString)\n";
00104     return false;
00105   }
00106 
00107   lst = mKMailIcalIfaceStub->incidences( type );
00108   if ( !mKMailIcalIfaceStub->ok() ) {
00109     kdError() << "Communication problem in ResourceIMAP::getIncidenceList()\n";
00110     return false;
00111   }
00112 
00113   return true;
00114 }
00115 
00116 bool ResourceIMAP::doOpen()
00117 {
00118   return true;
00119 }
00120 
00121 bool ResourceIMAP::load()
00122 {
00123   // Load each resource. Note: It's intentional to use & instead of &&
00124   // so we try all three, even if the first failed
00125   return loadAllEvents() & loadAllTasks() & loadAllJournals();
00126 }
00127 
00128 bool ResourceIMAP::loadAllEvents()
00129 {
00130   // Get the list of events
00131   QStringList lst;
00132   if ( !getIncidenceList( lst, "Calendar" ) )
00133     // The get failed
00134     return false;
00135 
00136   // We got a fresh list of events, so clean out the old ones
00137   mCalendar.deleteAllEvents();
00138 
00139   // Populate the calendar with the new events
00140   for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
00141     Incidence* i = parseIncidence( *it );
00142     if ( i ) {
00143       if ( i->type() == "Event" ) {
00144         mCalendar.addEvent(static_cast<Event*>(i));
00145         i->registerObserver( this );
00146       } else {
00147         kdDebug() << "Unknown incidence type " << i->type();
00148         delete i;
00149       }
00150     }
00151   }
00152 
00153   return true;
00154 }
00155 
00156 bool ResourceIMAP::loadAllTasks()
00157 {
00158   // Get the list of todos
00159   QStringList lst;
00160   if ( !getIncidenceList( lst, "Task" ) )
00161     // The get failed
00162     return false;
00163 
00164   // We got a fresh list of todos, so clean out the old ones
00165   mCalendar.deleteAllTodos();
00166 
00167   // Populate the calendar with the new todos
00168   for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
00169     Incidence* i = parseIncidence( *it );
00170     if ( i ) {
00171       if ( i->type() == "Todo" ) {
00172         mCalendar.addTodo(static_cast<Todo*>(i));
00173         i->registerObserver( this );
00174       } else {
00175         kdDebug() << "Unknown incidence type " << i->type();
00176         delete i;
00177       }
00178     }
00179   }
00180 
00181   return true;
00182 }
00183 
00184 bool ResourceIMAP::loadAllJournals()
00185 {
00186   // Get the list of journals
00187   QStringList lst;
00188   if ( !getIncidenceList( lst, "Journal" ) )
00189     // The get failed
00190     return false;
00191 
00192   // We got a fresh list of journals, so clean out the old ones
00193   mCalendar.deleteAllJournals();
00194 
00195   // Populate the calendar with the new journals
00196   for ( QStringList::Iterator it = lst.begin(); it != lst.end(); ++it ) {
00197     Incidence* i = parseIncidence( *it );
00198     if ( i ) {
00199       if ( i->type() == "Journal" ) {
00200         mCalendar.addJournal(static_cast<Journal*>(i));
00201         i->registerObserver( this );
00202       } else {
00203         kdDebug() << "Unknown incidence type " << i->type();
00204         delete i;
00205       }
00206     }
00207   }
00208 
00209   return true;
00210 }
00211 
00212 bool ResourceIMAP::save()
00213 {
00214   return false;
00215 }
00216 
00217 KABC::Lock *ResourceIMAP::lock()
00218 {
00219   return new KABC::LockNull( true );
00220 }
00221 
00222 /***********************************************
00223  * Adding and removing Events
00224  */
00225 
00226 bool ResourceIMAP::addEvent(Event *anEvent)
00227 {
00228   mCalendar.addEvent(anEvent);
00229   anEvent->registerObserver( this );
00230 
00231   if ( mSilent ) return true;
00232 
00233   // Call kmail ...
00234   if ( !connectToKMail() ) {
00235     kdError() << "DCOP error during addIncidence(QString)\n";
00236     return false;
00237   }
00238 
00239   mCurrentUID = anEvent->uid();
00240   QString vCal = mFormat.createScheduleMessage( anEvent, Scheduler::Request );
00241   bool rc = mKMailIcalIfaceStub->addIncidence( "Calendar", mCurrentUID, vCal );
00242   mCurrentUID = QString::null;
00243 
00244   if ( !mKMailIcalIfaceStub->ok() ) {
00245     kdError() << "Communication problem in ResourceIMAP::addEvent()\n";
00246     return false;
00247   }
00248 
00249   return rc;
00250 }
00251 
00252 // probably not really efficient, but...it works for now.
00253 void ResourceIMAP::deleteEvent(Event *event)
00254 {
00255   // Call kmail ...
00256   if ( !mSilent ) {
00257     if ( !connectToKMail() ) {
00258       kdError() << "DCOP error during "
00259                 << "ResourceIMAP::deleteIncidence(QString)\n";
00260     } else {
00261       mCurrentUID = event->uid();
00262       mKMailIcalIfaceStub->deleteIncidence( "Calendar", mCurrentUID );
00263     }
00264   }
00265 
00266   mCalendar.deleteEvent(event);
00267   mCurrentUID = QString::null;
00268 }
00269 
00270 
00271 /***********************************************
00272  * Getting Events
00273  */
00274 
00275 Event *ResourceIMAP::event( const QString &uid )
00276 {
00277   return mCalendar.event(uid);
00278 }
00279 
00280 // taking a QDate, this function will look for an eventlist in the dict
00281 // with that date attached -
00282 Event::List ResourceIMAP::rawEventsForDate( const QDate &qd, bool sorted )
00283 {
00284   return mCalendar.rawEventsForDate( qd, sorted );
00285 }
00286 
00287 
00288 Event::List ResourceIMAP::rawEvents( const QDate &start, const QDate &end,
00289                                           bool inclusive )
00290 {
00291   return mCalendar.rawEvents( start, end, inclusive );
00292 }
00293 
00294 Event::List ResourceIMAP::rawEventsForDate(const QDateTime &qdt)
00295 {
00296   return mCalendar.rawEventsForDate( qdt );
00297 }
00298 
00299 Event::List ResourceIMAP::rawEvents()
00300 {
00301   return mCalendar.rawEvents();
00302 }
00303 
00304 /***********************************************
00305  * Adding and removing Todos
00306  */
00307 
00308 bool ResourceIMAP::addTodo(Todo *todo)
00309 {
00310   mCalendar.addTodo(todo);
00311   todo->registerObserver( this );
00312 
00313   if ( mSilent ) return true;
00314 
00315   if ( !connectToKMail() ) {
00316     kdError() << "DCOP error during addTodo(QString)\n";
00317     return false;
00318   }
00319 
00320   mCurrentUID = todo->uid();
00321   QString vCal = mFormat.createScheduleMessage( todo, Scheduler::Request );
00322   bool rc = mKMailIcalIfaceStub->addIncidence( "Task", mCurrentUID, vCal );
00323   mCurrentUID = QString::null;
00324 
00325   if ( !mKMailIcalIfaceStub->ok() ) {
00326     kdError() << "Communication problem in ResourceIMAP::addTodo()\n";
00327     return false;
00328   }
00329 
00330   return rc;
00331 }
00332 
00333 void ResourceIMAP::deleteTodo(Todo *todo)
00334 {
00335   // call kmail ...
00336   if ( !mSilent ) {
00337     if ( !connectToKMail() ) {
00338       kdError() << "DCOP error during ResourceIMAP::deleteTodo(QString)\n";
00339     } else {
00340       mCurrentUID = todo->uid();
00341       mKMailIcalIfaceStub->deleteIncidence( "Task", mCurrentUID );
00342       mCurrentUID = QString::null;
00343     }
00344   }
00345   mCalendar.deleteTodo(todo);
00346 }
00347 
00348 /***********************************************
00349  * Getting Todos
00350  */
00351 
00352 Todo::List ResourceIMAP::rawTodos()
00353 {
00354   return mCalendar.rawTodos();
00355 }
00356 
00357 Todo *ResourceIMAP::todo( const QString &uid )
00358 {
00359   return mCalendar.todo(uid);
00360 }
00361 
00362 Todo::List ResourceIMAP::todos( const QDate &date )
00363 {
00364   return mCalendar.todos(date);
00365 }
00366 
00367 /***********************************************
00368  * Journal handling
00369  */
00370 
00371 bool ResourceIMAP::addJournal(Journal *journal)
00372 {
00373   mCalendar.addJournal(journal);
00374   journal->registerObserver( this );
00375 
00376   if ( mSilent ) return true;
00377 
00378   // call kmail ..
00379   if ( !connectToKMail() ) {
00380     kdError() << "DCOP error during addTodo(QString)\n";
00381     return false;
00382   }
00383 
00384   mCurrentUID = journal->uid();
00385   QString vCal = mFormat.createScheduleMessage( journal, Scheduler::Request );
00386   bool rc = mKMailIcalIfaceStub->addIncidence( "Journal", mCurrentUID, vCal );
00387   mCurrentUID = QString::null;
00388 
00389   if ( !mKMailIcalIfaceStub->ok() ) {
00390     kdError() << "Communication problem in ResourceIMAP::addJournal()\n";
00391     return false;
00392   }
00393 
00394   return rc;
00395 }
00396 
00397 void ResourceIMAP::deleteJournal(Journal *journal)
00398 {
00399   if( !journal )
00400     return;
00401 
00402   if ( !mSilent ) {
00403     if ( !connectToKMail() ) {
00404       kdError() << "DCOP error during ResourceIMAP::deleteJournal(QString)\n";
00405     } else {
00406       mCurrentUID = journal->uid();
00407       mKMailIcalIfaceStub->deleteIncidence( "Journal", mCurrentUID );
00408       mCurrentUID = QString::null;
00409     }
00410   }
00411   mCalendar.deleteJournal(journal);
00412 }
00413 
00414 
00415 Journal *ResourceIMAP::journal(const QDate &date)
00416 {
00417   return mCalendar.journal(date);
00418 }
00419 
00420 Journal *ResourceIMAP::journal(const QString &uid)
00421 {
00422   return mCalendar.journal(uid);
00423 }
00424 
00425 Journal::List ResourceIMAP::journals()
00426 {
00427   return mCalendar.journals();
00428 }
00429 
00430 /***********************************************
00431  * Alarm handling
00432  */
00433 
00434 Alarm::List ResourceIMAP::alarmsTo( const QDateTime &to )
00435 {
00436   return mCalendar.alarmsTo(to);
00437 }
00438 
00439 Alarm::List ResourceIMAP::alarms( const QDateTime &from, const QDateTime &to )
00440 {
00441   return mCalendar.alarms( from, to );
00442 }
00443 
00444 /***********************************************
00445  * update() (kind of slot)
00446  */
00447 
00448 // after changes are made to an event, this should be called.
00449 void ResourceIMAP::update(IncidenceBase *incidencebase)
00450 {
00451   if ( !connectToKMail() ) {
00452     kdError() << "DCOP error during ResourceIMAP::update(QString)\n";
00453     return;
00454   }
00455 
00456   QString type = incidencebase->type();
00457   if ( type == "Event" ) type = "Calendar";
00458   else if ( type == "Todo" ) type = "Task";
00459   else if ( type != "Journal" ) return;
00460 
00461   incidencebase->setSyncStatus(Event::SYNCMOD);
00462   incidencebase->setLastModified(QDateTime::currentDateTime());
00463   // we should probably update the revision number here,
00464   // or internally in the Event itself when certain things change.
00465   // need to verify with ical documentation.
00466 
00467   // Delete the old one and add the new version
00468   mCurrentUID = incidencebase->uid();
00469   QString vCal = mFormat.createScheduleMessage( incidencebase,
00470                                                 Scheduler::Request );
00471   mKMailIcalIfaceStub->deleteIncidence( type, mCurrentUID );
00472   mKMailIcalIfaceStub->addIncidence( type, mCurrentUID, vCal );
00473   mCurrentUID = QString::null;
00474 
00475   if ( !mKMailIcalIfaceStub->ok() ) {
00476     kdError() << "Communication problem in ResourceIMAP::addJournal()\n";
00477   }
00478 }
00479 
00480 KCal::Incidence* ResourceIMAP::parseIncidence( const QString& str )
00481 {
00482  Incidence* i = mFormat.fromString( str );
00483  return i;
00484 }
00485 
00486 bool ResourceIMAP::addIncidence( const QString& type, const QString& ical )
00487 {
00488   if( type != "Calendar" && type != "Task" && type != "Journal" )
00489     // Not an ical for us
00490     return false;
00491 
00492   Incidence* i = parseIncidence( ical );
00493   if ( !i ) return false;
00494   // Ignore events that come from us
00495   if ( !mCurrentUID.isNull() && mCurrentUID == i->uid() ) return true;
00496 
00497   mSilent = true;
00498   if ( type == "Calendar" && i->type() == "Event" ) {
00499     addEvent( static_cast<Event*>(i) );
00500     emit resourceChanged( this );
00501   } else if ( type == "Task" && i->type() == "Todo" ) {
00502     addTodo( static_cast<Todo*>(i) );
00503     emit resourceChanged( this );
00504   } else if ( type == "Journal" && i->type() == "Journal" ) {
00505     addJournal( static_cast<Journal*>(i) );
00506     emit resourceChanged( this );
00507   }
00508   mSilent = false;
00509 
00510   return true;
00511 }
00512 
00513 void ResourceIMAP::deleteIncidence( const QString& type, const QString& uid )
00514 {
00515   if( type != "Calendar" && type != "Task" && type != "Journal" )
00516     // Not an ical for us
00517     return;
00518 
00519   // Ignore events that come from us
00520   if ( !mCurrentUID.isNull() && mCurrentUID == uid ) return;
00521 
00522   mSilent = true;
00523   if ( type == "Calendar" ) {
00524     Event* e = event( uid );
00525     if( e ) {
00526       deleteEvent( e );
00527       emit resourceChanged( this );
00528     }
00529   } else if ( type == "Task" ) {
00530     Todo* t = todo( uid );
00531     if( t ) {
00532       deleteTodo( t );
00533       emit resourceChanged( this );
00534     }
00535   } else if ( type == "Journal" ) {
00536     Journal* j = journal( uid );
00537     if( j ) {
00538       deleteJournal( j );
00539       emit resourceChanged( this );
00540     }
00541   }
00542   mSilent = false;
00543 }
00544 
00545 void ResourceIMAP::slotRefresh( const QString& type )
00546 {
00547   if ( type == "Calendar" )
00548     loadAllEvents();
00549   else if ( type == "Task" )
00550     loadAllTasks();
00551   else if ( type == "Journal" )
00552     loadAllJournals();
00553 }
00554 
00555 bool ResourceIMAP::connectToKMail() const
00556 {
00557   if ( !mKMailIcalIfaceStub ) {
00558     QString error;
00559     QCString dcopService;
00560     int result = KDCOPServiceStarter::self()->
00561       findServiceFor( "DCOP/ResourceBackend/IMAP", QString::null,
00562                       QString::null, &error, &dcopService );
00563     if ( result != 0 ) {
00564       kdDebug(5800) << "Couldn't connect to the IMAP resource backend\n";
00565       // TODO: You might want to show "error" (if not empty) here, using e.g. KMessageBox
00566       return false;
00567     }
00568 
00569     mKMailIcalIfaceStub = new KMailICalIface_stub( kapp->dcopClient(),
00570                                                    dcopService, dcopObjectId );
00571 
00572     // Attach to the KMail signals
00573     if ( !connectKMailSignal( "incidenceAdded(QString,QString)",
00574                               "addIncidence(QString,QString)" ) ) {
00575       kdError() << "DCOP connection to incidenceAdded failed" << endl;
00576     }
00577     if ( !connectKMailSignal( "incidenceDeleted(QString,QString)",
00578                               "deleteIncidence(QString,QString)" ) ) {
00579       kdError() << "DCOP connection to incidenceDeleted failed" << endl;
00580     }
00581     if ( !connectKMailSignal( "signalRefresh(QString)",
00582                               "slotRefresh(QString)" ) ) {
00583       kdError() << "DCOP connection to signalRefresh failed" << endl;
00584     }
00585   }
00586 
00587   return ( mKMailIcalIfaceStub != 0 );
00588 }
00589 
00590 bool ResourceIMAP::connectKMailSignal( const QCString& signal,
00591                                        const QCString& method ) const
00592 {
00593   ResourceIMAP* _this = const_cast<ResourceIMAP*>( this );
00594   return _this->connectDCOPSignal( "kmail", dcopObjectId, signal, method,
00595                                    false );
00596 }
00597 
00598 void ResourceIMAP::unregisteredFromDCOP( const QCString& appId )
00599 {
00600   if ( mKMailIcalIfaceStub && mKMailIcalIfaceStub->app() == appId ) {
00601     // Delete the stub so that the next time we need the addressbook,
00602     // we'll know that we need to start a new one.
00603     delete mKMailIcalIfaceStub;
00604     mKMailIcalIfaceStub = 0;
00605   }
00606 }
00607 
00608 
00609 void ResourceIMAP::setTimeZoneId( const QString& tzid )
00610 {
00611   mCalendar.setTimeZoneId( tzid );
00612 }
00613 
00614 #include "resourceimap.moc"
00615 
KDE Logo
This file is part of the documentation for libkcal Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:36:23 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003