kitchensync Library API Documentation

organizerpart.cpp

00001 
00002 #include <qcheckbox.h>
00003 
00004 #include <ksimpleconfig.h>
00005 #include <kdebug.h>
00006 #include <kiconloader.h>
00007 #include <kmessagebox.h>
00008 #include <kparts/genericfactory.h>
00009 
00010 #include <libkcal/icalformat.h>
00011 #include <libkcal/calendarlocal.h>
00012 
00013 #include <eventsyncee.h>
00014 #include <todosyncee.h>
00015 #include <syncer.h>
00016 
00017 #include <mainwindow.h>
00018 
00019 #include "organizerpart.h"
00020 
00021 //#include "return.h"
00022 //#include "sync.h"
00023 
00024 typedef KParts::GenericFactory< KSync::OrganizerPart> OrganizerPartFactory;
00025 K_EXPORT_COMPONENT_FACTORY( liborganizerpart, OrganizerPartFactory )
00026 
00027 using namespace KSync ;
00028 
00029 OrganizerPart::OrganizerPart(QWidget *parent, const char *name,
00030                  QObject *, const char *, const QStringList & )
00031   : ManipulatorPart( parent, name )
00032 {
00033   setInstance(OrganizerPartFactory::instance() );
00034   m_pixmap = KGlobal::iconLoader()->loadIcon("korganizer", KIcon::Desktop, 48 );
00035 
00036   kdDebug() << "OragnizerPart" << endl;
00037 }
00038 OrganizerPart::~OrganizerPart()
00039 {
00040 }
00041 QString OrganizerPart::iconName()const {
00042     return QString::fromLatin1("korganizer");
00043 }
00044 QPixmap* OrganizerPart::pixmap()
00045 {
00046     return &m_pixmap;
00047 }
00048 QString OrganizerPart::type()const {
00049     return QString::fromLatin1("Organizer");
00050 }
00051 QString OrganizerPart::name()const {
00052     return i18n("Organizer");
00053 }
00054 QString OrganizerPart::description()const {
00055     return i18n("This part is responsible for syncing your Calendar.");
00056 }
00057 bool OrganizerPart::hasGui()const {
00058     return false;
00059 }
00060 bool OrganizerPart::configIsVisible()const {
00061     return true;
00062 }
00063 QWidget* OrganizerPart::configWidget()
00064 {
00065     m_config = new OrganizerDialogBase();
00066 
00067     if ( isEvolutionSync() )
00068         m_config->ckbEvo->setChecked( true );
00069     else{
00070         m_config->urlReq->setURL( core()->currentProfile().path("OrganizerPart") );
00071     }
00072 
00073   return (QWidget*) m_config;
00074 }
00075 
00076 bool OrganizerPart::isEvolutionSync()const {
00077     QString path;
00078     path = core()->currentProfile().path( "OrganizerPart" );
00079 
00080     return ( path == QString::fromLatin1("evolution" ) ) ;
00081 }
00082 
00083 KAboutData *OrganizerPart::createAboutData()
00084 {
00085   return new KAboutData("KSyncOrganizerPart", I18N_NOOP("Sync organizer part"), "0.0" );
00086 }
00087 
00088 void OrganizerPart::slotConfigOk()
00089 {
00090     Profile prof = core()->currentProfile();
00091     if ( m_config->ckbEvo->isChecked() )
00092         prof.setPath("OrganizerPart", "evolution");
00093     else
00094         prof.setPath("OrganizerPart", m_config->urlReq->url() );
00095 
00096     core()->profileManager()->replaceProfile( prof );
00097     core()->profileManager()->setCurrentProfile( prof );
00098 }
00099 /* Do it for Events + Todos
00100  * The 10 Stages to synced data
00101  * 0. get the time zone id
00102  * 1. get the currentProfile and currentKonnector
00103  * 2. get the paths + the information about using meta data
00104  *    from the Konnector
00105  * 3. search our Syncees
00106  * 4. load the File from currentProfile
00107  * 5. If meta data collect it currentProfile.uid() + currentKonnectorProf.uid()
00108  *    + name for the MetaInformation filename
00109  * 6. SYNC using our own algorithm
00110  * 7. write back meta data if necessary
00111  * 8. write back file
00112  * 9. append the Syncee to the out list
00113  * 10. have a party and get drunk
00114  */
00115 void OrganizerPart::sync( const SynceeList &in,
00116                           SynceeList &out )
00117 {
00118     /* 0. */
00119     KConfig conf("korganizerrc");
00120     conf.setGroup("Time & Date");
00121     QString timeZoneId = conf.readEntry("TimeZoneId", QString::fromLatin1("UTC") );
00122     kdDebug(5222) << " Time & Date " << timeZoneId << endl;
00123 
00124     /* 1. is fairly easy */
00125     Profile prof = core()->currentProfile();
00126     KonnectorProfile kon = core()->currentKonnectorProfile();
00127 
00128     /* 2. too */
00129     QString path = prof.path( "OrganizerPart"  );
00130     QString meta =  kon.uid()+"/"+prof.uid() + "organizer.rc";
00131     bool met = kon.kapabilities().isMetaSyncingEnabled();
00132 
00133     /* 3. */
00134     EventSyncee *evSyncee = in.eventSyncee();
00135     TodoSyncee *toSyncee = in.todoSyncee();
00136     if (!evSyncee && !toSyncee) {
00137         done();
00138         return; // did not find both of them
00139     }
00140 
00141     /* 4. load */
00142     EventSyncee* events =0l;
00143     TodoSyncee* todos = 0l;
00144     if (evSyncee )
00145        events = loadEvents( path, timeZoneId );
00146     if (toSyncee )
00147         todos = loadTodos( path, timeZoneId );
00148 
00149     /* 5. meta data */
00150     if ( met )
00151         doMeta( events, todos, meta );
00152     //else {
00153     // set the sync MODE FIXME
00154     //}
00155     /* 6.  sync */
00156     Syncer sync( core()->syncUi(), core()->syncAlgorithm() );
00157     if (evSyncee ) {
00158         events->setSource( i18n("Organizer") );
00159         sync.addSyncee(evSyncee);
00160         sync.addSyncee(events);
00161         sync.sync();
00162         sync.clear();
00163     }
00164     if (toSyncee ) {
00165         todos->setSource( i18n("Todolist") );
00166         sync.addSyncee( toSyncee );
00167         sync.addSyncee( todos );
00168         sync.sync();
00169         sync.clear();
00170     }
00171 
00172     if ( confirmBeforeWriting() ) {
00173         switch ( KMessageBox::questionYesNo(0, i18n("Do you want to write back todolist and calendar?"), i18n("Save"),
00174                                             KStdGuiItem::save(), KStdGuiItem::dontSave() ) ) {
00175         case KMessageBox::No:{
00176             delete todos;
00177             delete events;
00178             done();
00179             return;
00180 
00181             break;
00182         }
00183         default:
00184             break;
00185         }
00186     }
00187 
00188     /* 7. write back meta */
00189     if ( met )
00190         writeMeta( events, todos, meta );
00191 
00192     /* 8. write back data */
00193     save( events, todos, path, timeZoneId );
00194 
00195     /* 8.1 take care of the IdHelpers.... */
00196 
00197     /* 9. */
00198     if (events)
00199       out.append( events );
00200 
00201     if (todos)
00202       out.append( todos );
00203     done();
00204 }
00205 
00206 //AddressBookSyncee* ANY
00207 TodoSyncee* OrganizerPart::loadTodos( const QString& pa, const QString& timeZoneId ) {
00208     TodoSyncee* syncee = new TodoSyncee();
00209     KCal::CalendarLocal cal(timeZoneId);
00210     cal.load(path( Todo, pa ) );
00211     KCal::Todo::List todos = cal.rawTodos();
00212     if ( todos.isEmpty() ) {
00213         return syncee;
00214     }
00215 
00216     KCal::Todo::List::ConstIterator it;
00217     TodoSyncEntry* entry =0 ;
00218     for ( it = todos.begin(); it != todos.end(); ++it ) {
00219         entry = new TodoSyncEntry( (*it)->clone() ) ;
00220         syncee->addEntry( entry );
00221     }
00222     return syncee;
00223 }
00224 EventSyncee* OrganizerPart::loadEvents(const QString& pa,  const QString& timeZoneId) {
00225     EventSyncee* syncee = new EventSyncee();
00226     KCal::CalendarLocal cal(timeZoneId);
00227     cal.load( path(Calendar, pa) );
00228     KCal::Event::List events = cal.rawEvents();
00229     if ( events.isEmpty() ) {
00230         return syncee;
00231     }
00232 
00233     KCal::Event::List::ConstIterator it;
00234     EventSyncEntry* entry;
00235     for ( it = events.begin(); it != events.end(); ++it ) {
00236         entry = new EventSyncEntry( (*it)->clone() );
00237         syncee->addEntry( entry );
00238         kdDebug(5222) << "Start Date of loaded " <<  entry->incidence()->dtStart().toString() << " " << entry->incidence()->uid() << endl;
00239     }
00240     return syncee;
00241 }
00242 /*
00243  * For meta informations we're using a KConfig file
00244  * we've one Group for each id
00245  * and we save the timestamp
00246  * First we try to find modified
00247  * then added and removed
00248  * Modified is quite easy to find
00249  * if there hasGroup(uid) and timestamp differs it was
00250  * modified.
00251  * added: if not hasGroup(uid) added
00252  * removed: if it's inside the Config file but not in
00253  * the current set of data
00254  */
00255 void OrganizerPart::doMeta( EventSyncee* evSyncee,
00256                             TodoSyncee* toSyncee,
00257                             const QString& path ) {
00258     QString str = QDir::homeDirPath();
00259     str += "/.kitchensync/meta/konnector-" + path;
00260     if (!QFile::exists( str ) ) {
00261         if (evSyncee ) {
00262             evSyncee->setFirstSync( true );
00263             evSyncee->setSyncMode( Syncee::MetaMode );
00264         }
00265         if (toSyncee) {
00266             toSyncee->setFirstSync( true );
00267             toSyncee->setSyncMode( Syncee::MetaMode );
00268         }
00269         return;
00270     }
00271     KSimpleConfig conf( str );
00272 
00273     /* check if event and or todosyncee are valid */
00274     if (evSyncee )
00275         doMetaIntern(evSyncee, &conf, "events-" );
00276 
00277     if (toSyncee )
00278         doMetaIntern(toSyncee, &conf, "todos-" );
00279 }
00280 void OrganizerPart::doMetaIntern( Syncee* syncee,
00281                                   KSimpleConfig* conf,
00282                                   const QString& key) {
00283     syncee->setSyncMode( Syncee::MetaMode );
00284     SyncEntry* entry;
00285     QStringList ids;
00286     QString timestmp;
00287 
00288     /* mod + added */
00289     for ( entry = syncee->firstEntry(); entry; entry = syncee->nextEntry() ) {
00290         ids << entry->id();
00291         /* has group see if modified */
00292         if ( conf->hasGroup( key + entry->id() ) ) {
00293             conf->setGroup( key + entry->id() );
00294             timestmp = conf->readEntry( "time");
00295 
00296             /* timestamp mismatch */
00297             if ( timestmp != entry->timestamp() )
00298                 entry->setState(SyncEntry::Modified );
00299 
00300         }else { // added
00301             entry->setState( SyncEntry::Added );
00302         }
00303 
00304     }
00305     /* now let's find the removed items */
00306     QStringList  groups = conf->groupList();
00307     QStringList::Iterator it;
00308     // first find the groups for our key
00309     for ( it = groups.begin(); it != groups.end(); ++it ) {
00310         /* if group starts with the key */
00311         if ( (*it).startsWith(key ) ) { // right group
00312             QString id = (*it).mid( key.length() );
00313             kdDebug(5222) << "OrganizerPart Meta Gathering: "
00314                       << id << endl;
00315 
00316             /*
00317              * the previous saved list of ids
00318              *  does not contain this id
00319              * ->REMOVED
00320              * items were removed we need to create an item
00321              * with just a uid......
00322              * let's find out which item to create or have
00323              * 2 methods sharing 95% of code
00324              */
00325             if (!ids.contains( id )) {
00326                 if ( syncee->type() == "TodoSyncee" ) {
00327                     KCal::Todo *todo = new KCal::Todo();
00328                     todo->setUid( id );
00329                     TodoSyncEntry* entry = new TodoSyncEntry( todo );
00330                     syncee->addEntry( entry );
00331                     entry->setState( SyncEntry::Removed );
00332 
00333                 }else { // organizer
00334                     KCal::Event* ev = new KCal::Event();
00335                     ev->setUid( id );
00336                     EventSyncEntry* entry = new EventSyncEntry( ev );
00337                     syncee->addEntry( entry );
00338                     entry->setState( SyncEntry::Removed );
00339                     kdDebug(5222) << "Removed " << entry->id() << endl;
00340                 }
00341             }
00342         }
00343     }
00344 }
00345 
00349 void OrganizerPart::writeMeta( EventSyncee* evSyncee,
00350                                TodoSyncee* toSyncee,
00351                                const QString& path) {
00352     QString str = QDir::homeDirPath();
00353     str += "/.kitchensync/meta/konnector-" + path;
00354     if (!QFile::exists( str ) ) {
00355         KonnectorProfile kon = core()->currentKonnectorProfile();
00356         QDir dir;
00357         dir.mkdir( QDir::homeDirPath() + "/.kitchensync");
00358         dir.mkdir( QDir::homeDirPath() + "/.kitchensync/meta");
00359         dir.mkdir( QDir::homeDirPath() + "/.kitchensync/meta/konnector-" + kon.uid() );
00360     }
00361     KSimpleConfig conf( str );
00362     /* clear config before */
00363     QStringList groups = conf.groupList();
00364     QStringList::Iterator it;
00365     for (it = groups.begin(); it != groups.end(); ++it ) {
00366         conf.deleteGroup( (*it) );
00367     }
00368     if (evSyncee )
00369         writeMetaIntern( evSyncee, &conf, "events-");
00370     if (toSyncee)
00371         writeMetaIntern( toSyncee, &conf, "todos-");
00372 }
00373 void OrganizerPart::writeMetaIntern( Syncee* syncee,
00374                                      KSimpleConfig* conf,
00375                                      const QString& key ) {
00376     SyncEntry* entry;
00377     for (entry = syncee->firstEntry(); entry; entry= syncee->nextEntry() ) {
00378         if (entry->state() == SyncEntry::Removed )
00379             continue;
00380 
00381         conf->setGroup( key + entry->id() );
00382         conf->writeEntry( "time", entry->timestamp() );
00383     }
00384 }
00385 void OrganizerPart::save( EventSyncee* evSyncee,
00386                           TodoSyncee* toSyncee,
00387                           const QString& pa,
00388                           const QString& timeZoneId) {
00389     KCal::CalendarLocal* loc = new KCal::CalendarLocal(timeZoneId);
00390     EventSyncEntry* evEntry=0l;
00391     TodoSyncEntry* toEntry=0l;
00392     if (evSyncee) {
00393       for ( evEntry = (EventSyncEntry*)evSyncee->firstEntry();
00394             evEntry;
00395             evEntry = (EventSyncEntry*)evSyncee->nextEntry() )
00396       {
00397           if (evEntry->state() != SyncEntry::Removed )
00398               loc->addEvent((KCal::Event*)evEntry->incidence()->clone()  );
00399       }
00400     }
00401 
00402     /*
00403      * For Evolution we will save here
00404      */
00405     if (isEvolutionSync() ) {
00406         loc->save( path( Calendar, pa ) );
00407         delete loc;
00408         loc = new KCal::CalendarLocal( timeZoneId );
00409     }
00410 
00411     if (toSyncee){
00412       for ( toEntry = (TodoSyncEntry*)toSyncee->firstEntry();
00413             toEntry;
00414             toEntry = (TodoSyncEntry*)toSyncee->nextEntry() )
00415       {
00416           if (toEntry->state() != SyncEntry::Removed )
00417               loc->addTodo((KCal::Todo*)toEntry->todo()->clone() );
00418       }
00419     }
00420 
00421     loc->save( path( Todo, pa)  );
00422 
00423     /* WE NEED TO LEAK HERE CAUSE CLONE SEAMS TO FAIL
00424      * I'll INVESTIGATE THIS FURTHER
00425      * FIXME let the libkonnector be more verbose
00426      * let us tell us if it synced successfully or not
00427      * there we could also delete the calendar then....
00428      * More Info now:
00429      * We add these incidence to the calendar and it want to take ownership
00430      * the CalendarLocals internal QPtrList is set to AutoDelete
00431      * which will delete even our todos..
00432      * so we need to clone before adding it.
00433      * FIXED
00434      */
00435     delete loc;
00436 }
00437 
00438 /*
00439  * we will return the right path
00440  * for the right calendar system!
00441  */
00442 QString OrganizerPart::path( Data d, const QString& path ) {
00443     if ( !isEvolutionSync() ) {
00444         kdDebug(5222) << "Syncing with KDE and not Evolution " << endl;
00445         return path;
00446     }
00447 
00448     QString str;
00449     switch(d) {
00450     case Calendar:
00451         str = QDir::homeDirPath() + "/evolution/local/Calendar/calendar.ics";
00452         break;
00453     case Todo:
00454     default:
00455         str = QDir::homeDirPath()+ "/evolution/local/Tasks/tasks.ics";
00456         break;
00457     }
00458     return str;
00459 }
00460 
00461 #include "organizerpart.moc"
KDE Logo
This file is part of the documentation for kitchensync Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jan 31 15:53:45 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003