kpilot Library API Documentation

todo-conduit.cc

00001 /* todo-conduit.cc  Todo-Conduit for syncing KPilot and KOrganizer
00002 **
00003 ** Copyright (C) 2002-2003 Reinhold Kainhofer
00004 ** Copyright (C) 1998-2001 Dan Pilone
00005 ** Copyright (C) 1998-2000 Preston Brown
00006 ** Copyright (C) 1998 Herwin-Jan Steehouwer
00007 ** Copyright (C) 2001 Cornelius Schumacher
00008 **
00009 ** This file is part of the todo conduit, a conduit for KPilot that
00010 ** synchronises the Pilot's todo application with the outside world,
00011 ** which currently means KOrganizer.
00012 */
00013 
00014 /*
00015 ** This program is free software; you can redistribute it and/or modify
00016 ** it under the terms of the GNU General Public License as published by
00017 ** the Free Software Foundation; either version 2 of the License, or
00018 ** (at your option) any later version.
00019 **
00020 ** This program is distributed in the hope that it will be useful,
00021 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00023 ** GNU General Public License for more details.
00024 **
00025 ** You should have received a copy of the GNU General Public License
00026 ** along with this program in a file called COPYING; if not, write to
00027 ** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00028 ** MA 02111-1307, USA.
00029 */
00030 
00031 /*
00032 ** Bug reports and questions can be sent to kde-pim@kde.org
00033 */
00034 
00035 static const char *TodoConduit_id = "$Id: todo-conduit.cc,v 1.41 2004/01/15 09:58:49 kainhofe Exp $";
00036 
00037 #include <options.h>
00038 #include <unistd.h>
00039 
00040 #include <qdatetime.h>
00041 #include <qtimer.h>
00042 #include <qtextcodec.h>
00043 
00044 #include <pilotUser.h>
00045 #include <kconfig.h>
00046 
00047 #include <libkcal/calendar.h>
00048 #include <libkcal/todo.h>
00049 
00050 
00051 /*
00052 ** KDE 2.2 uses class KORecurrence in a different header file.
00053 */
00054 #ifdef KDE2
00055 #define DateList_t QDateList
00056 #define DateListIterator_t QDateListIterator
00057 #else
00058 #define DateList_t KCal::DateList
00059 #define DateListIterator_t KCal::DateList::ConstIterator
00060 #endif
00061 
00062 #include <pilotSerialDatabase.h>
00063 #include <pilotLocalDatabase.h>
00064 
00065 #include "todo-conduit.moc"
00066 
00067 // define conduit versions, one for the version when categories were synced for the first time, and the current version number
00068 #define CONDUIT_VERSION_CATEGORYSYNC 10
00069 #define CONDUIT_VERSION 10
00070 
00071 
00072 
00073 TodoConduitPrivate::TodoConduitPrivate(KCal::Calendar *b) :
00074     VCalConduitPrivateBase(b)
00075 {
00076     fAllTodos.setAutoDelete(false);
00077 }
00078 
00079 void TodoConduitPrivate::addIncidence(KCal::Incidence*e)
00080 {
00081     fAllTodos.append(static_cast<KCal::Todo*>(e));
00082     fCalendar->addTodo(static_cast<KCal::Todo*>(e));
00083 }
00084 
00085 int TodoConduitPrivate::updateIncidences()
00086 {
00087     fAllTodos = fCalendar->todos();
00088     fAllTodos.setAutoDelete(false);
00089     return fAllTodos.count();
00090 }
00091 
00092 
00093 void TodoConduitPrivate::removeIncidence(KCal::Incidence *e)
00094 {
00095     fAllTodos.remove(static_cast<KCal::Todo*>(e));
00096     fCalendar->deleteTodo(static_cast<KCal::Todo*>(e));
00097 }
00098 
00099 
00100 
00101 KCal::Incidence *TodoConduitPrivate::findIncidence(recordid_t id)
00102 {
00103     KCal::Todo::List::ConstIterator it;
00104         for( it = fAllTodos.begin(); it != fAllTodos.end(); ++it ) {
00105                 KCal::Todo *todo = *it;
00106         if ((recordid_t)(todo->pilotId()) == id) return todo;
00107     }
00108 
00109     return 0L;
00110 }
00111 
00112 
00113 
00114 KCal::Incidence *TodoConduitPrivate::findIncidence(PilotAppCategory*tosearch)
00115 {
00116     PilotTodoEntry*entry=dynamic_cast<PilotTodoEntry*>(tosearch);
00117     if (!entry) return 0L;
00118 
00119     QString title=entry->getDescription();
00120     QDateTime dt=readTm( entry->getDueDate() );
00121 
00122     KCal::Todo::List::ConstIterator it;
00123         for( it = fAllTodos.begin(); it != fAllTodos.end(); ++it ) {
00124                 KCal::Todo *event = *it;
00125         if ( (event->dtDue().date() == dt.date()) && (event->summary() == title) ) return event;
00126     }
00127     return 0L;
00128 }
00129 
00130 
00131 
00132 KCal::Incidence *TodoConduitPrivate::getNextIncidence()
00133 {
00134     if (reading) {
00135                 ++fAllTodosIterator;
00136                 if ( fAllTodosIterator == fAllTodos.end() ) return 0;
00137         } else {
00138             reading=true;
00139                 fAllTodosIterator = fAllTodos.begin();
00140         }
00141         return *fAllTodosIterator;
00142 }
00143 
00144 
00145 
00146 KCal::Incidence *TodoConduitPrivate::getNextModifiedIncidence()
00147 {
00148 FUNCTIONSETUP;
00149     KCal::Todo*e=0L;
00150     if (!reading)
00151     {
00152         reading=true;
00153                 fAllTodosIterator = fAllTodos.begin();
00154                 if ( fAllTodosIterator != fAllTodos.end() ) e=*fAllTodosIterator;
00155     }
00156     else
00157     {
00158         ++fAllTodosIterator;
00159     }
00160     while (fAllTodosIterator != fAllTodos.end() &&
00161         e && e->syncStatus()!=KCal::Incidence::SYNCMOD)
00162     {
00163         ++fAllTodosIterator;
00164         e=*fAllTodosIterator;
00165 #ifdef DEBUG
00166 if (e)
00167 DEBUGCONDUIT<< e->summary()<<" had SyncStatus="<<e->syncStatus()<<endl;
00168 #endif
00169     }
00170         if ( fAllTodosIterator == fAllTodos.end() ) return 0;
00171     else return *fAllTodosIterator;
00172 }
00173 
00174 
00175 
00176 /****************************************************************************
00177  *                          TodoConduit class                               *
00178  ****************************************************************************/
00179 
00180 TodoConduit::TodoConduit(KPilotDeviceLink *d,
00181     const char *n,
00182     const QStringList &a) : VCalConduitBase(d,n,a)
00183 {
00184     FUNCTIONSETUP;
00185 #ifdef DEBUG
00186     DEBUGCONDUIT << TodoConduit_id << endl;
00187 #endif
00188     fConduitName=i18n("To-do");
00189         
00190         (void) TodoConduit_id;
00191 }
00192 
00193 
00194 
00195 TodoConduit::~TodoConduit()
00196 {
00197 //  FUNCTIONSETUP;
00198 }
00199 
00200 
00201 
00202 void TodoConduit::_setAppInfo()
00203 {
00204     FUNCTIONSETUP;
00205     // get the address application header information
00206     int appLen = pack_ToDoAppInfo(&fTodoAppInfo, 0, 0);
00207     unsigned char *buffer = new unsigned char[appLen];
00208     pack_ToDoAppInfo(&fTodoAppInfo, buffer, appLen);
00209     if (fDatabase) fDatabase->writeAppBlock(buffer, appLen);
00210     if (fLocalDatabase) fLocalDatabase->writeAppBlock(buffer, appLen);
00211     delete[] buffer;
00212 }
00213 void TodoConduit::_getAppInfo()
00214 {
00215     FUNCTIONSETUP;
00216     // get the address application header information
00217     unsigned char *buffer =
00218         new unsigned char[PilotTodoEntry::APP_BUFFER_SIZE];
00219     int appLen = fDatabase->readAppBlock(buffer,PilotTodoEntry::APP_BUFFER_SIZE);
00220 
00221     unpack_ToDoAppInfo(&fTodoAppInfo, buffer, appLen);
00222     delete[]buffer;
00223     buffer = NULL;
00224 
00225 #ifdef DEBUG
00226     DEBUGCONDUIT << fname << " lastUniqueId"
00227         << fTodoAppInfo.category.lastUniqueID << endl;
00228 #endif
00229     for (int i = 0; i < 16; i++)
00230     {
00231 #ifdef DEBUG
00232         DEBUGCONDUIT << fname << " cat " << i << " =" <<
00233             fTodoAppInfo.category.name[i] << endl;
00234 #endif
00235     }
00236 
00237 }
00238 
00239 
00240 
00241 const QString TodoConduit::getTitle(PilotAppCategory*de)
00242 {
00243     PilotTodoEntry*d=dynamic_cast<PilotTodoEntry*>(de);
00244     if (d) return QString(d->getDescription());
00245     return QString::null;
00246 }
00247 
00248 
00249 
00250 void TodoConduit::readConfig()
00251 {
00252     FUNCTIONSETUP;
00253     VCalConduitBase::readConfig();
00254     // determine if the categories have ever been synce. Needed to prevent loosing the categories on the desktop.
00255     // also use a full sync for the first time to make sure the palm categories are really transferred to the desktop
00256     categoriesSynced = fConfig->readNumEntry("ConduitVersion", 0)>=CONDUIT_VERSION_CATEGORYSYNC;
00257     if (!categoriesSynced & !isFullSync() ) fSyncDirection=SyncAction::eFullSync;
00258 #ifdef DEBUG
00259     DEBUGCONDUIT<<"categoriesSynced="<<categoriesSynced<<endl;
00260 #endif
00261 }
00262 
00263 
00264 
00265 void TodoConduit::postSync()
00266 {
00267     FUNCTIONSETUP;
00268     VCalConduitBase::postSync();
00269     fConfig->setGroup(configGroup());
00270     // after this successful sync the categories have been synced for sure
00271     fConfig->writeEntry("ConduitVersion", CONDUIT_VERSION);
00272     _setAppInfo();
00273 }
00274 
00275 
00276 
00277 PilotRecord*TodoConduit::recordFromIncidence(PilotAppCategory*de, const KCal::Incidence*e)
00278 {
00279     // don't need to check for null pointers here, the recordFromIncidence(PTE*, KCal::Todo*) will do that.
00280     PilotTodoEntry *tde = dynamic_cast<PilotTodoEntry*>(de);
00281     const KCal::Todo *te = dynamic_cast<const KCal::Todo*>(e);
00282 
00283     return recordFromTodo(tde, te);
00284 }
00285 
00286 
00287 
00288 PilotRecord*TodoConduit::recordFromTodo(PilotTodoEntry*de, const KCal::Todo*todo)
00289 {
00290     FUNCTIONSETUP;
00291     if (!de || !todo) {
00292 #ifdef DEBUG
00293         DEBUGCONDUIT<<fname<<": NULL todo given... Skipping it"<<endl;
00294 #endif
00295         return NULL;
00296     }
00297 
00298     // set secrecy, start/end times, alarms, recurrence, exceptions, summary and description:
00299     if (todo->secrecy()!=KCal::Todo::SecrecyPublic) de->makeSecret();
00300 
00301     // update it from the iCalendar Todo.
00302 
00303     if (todo->hasDueDate()) {
00304         struct tm t = writeTm(todo->dtDue());
00305         de->setDueDate(t);
00306         de->setIndefinite(0);
00307     } else {
00308         de->setIndefinite(1);
00309     }
00310 
00311     // TODO: take recurrence (code in VCAlConduit) from ActionNames
00312 
00313     setCategory(de, todo);
00314 
00315     // TODO: sync the alarm from ActionNames. Need to extend PilotTodoEntry
00316     de->setPriority(todo->priority());
00317 
00318     de->setComplete(todo->isCompleted());
00319 
00320     // what we call summary pilot calls description.
00321     de->setDescription(todo->summary());
00322 
00323     // what we call description pilot puts as a separate note
00324     de->setNote(todo->description());
00325 
00326 #ifdef DEBUG
00327 DEBUGCONDUIT<<"-------- "<<todo->summary()<<endl;
00328 #endif
00329     return de->pack();
00330 }
00331 
00332 
00333 
00334 void TodoConduit::preRecord(PilotRecord*r)
00335 {
00336     FUNCTIONSETUP;
00337     if (!categoriesSynced && r)
00338     {
00339         const PilotAppCategory*de=newPilotEntry(r);
00340         KCal::Incidence *e = fP->findIncidence(r->getID());
00341         setCategory(dynamic_cast<KCal::Todo*>(e), dynamic_cast<const PilotTodoEntry*>(de));
00342     }
00343 }
00344 
00345 
00346 
00347 void TodoConduit::setCategory(PilotTodoEntry*de, const KCal::Todo*todo)
00348 {
00349     if (!de || !todo) return;
00350     de->setCategory(_getCat(todo->categories(), de->getCategoryLabel()));
00351 }
00352 
00353 
00354 
00359 QString TodoConduit::_getCat(const QStringList cats, const QString curr) const
00360 {
00361     int j;
00362     if (cats.size()<1) return QString::null;
00363     if (cats.contains(curr)) return curr;
00364     for ( QStringList::ConstIterator it = cats.begin(); it != cats.end(); ++it ) {
00365         for (j=1; j<=15; j++)
00366         {
00367             QString catName = PilotAppCategory::codec()->
00368                 toUnicode(fTodoAppInfo.category.name[j]);
00369             if (!(*it).isEmpty() && !(*it).compare( catName ) )
00370             {
00371                 return catName;
00372             }
00373         }
00374     }
00375     // If we have a free label, return the first possible cat
00376     QString lastName(fTodoAppInfo.category.name[15]);
00377     if (lastName.isEmpty()) return cats.first();
00378     return QString::null;
00379 }
00380 
00381 
00382 
00383 KCal::Incidence *TodoConduit::incidenceFromRecord(KCal::Incidence *e, const PilotAppCategory *de)
00384 {
00385     return dynamic_cast<KCal::Incidence*>(incidenceFromRecord(dynamic_cast<KCal::Todo*>(e), dynamic_cast<const PilotTodoEntry*>(de)));
00386 }
00387 
00388 
00389 
00390 KCal::Todo *TodoConduit::incidenceFromRecord(KCal::Todo *e, const PilotTodoEntry *de)
00391 {
00392     FUNCTIONSETUP;
00393 
00394     KCal::Todo*vtodo=e;
00395     if (!vtodo)
00396     {
00397 #ifdef DEBUG
00398         DEBUGCONDUIT<<fname<<": null todo entry given. skipping..."<<endl;
00399 #endif
00400         return NULL;
00401     }
00402 
00403     e->setOrganizer(fCalendar->getEmail());
00404     e->setPilotId(de->getID());
00405     e->setSyncStatus(KCal::Incidence::SYNCNONE);
00406     e->setSecrecy(de->isSecret() ? KCal::Todo::SecrecyPrivate : KCal::Todo::SecrecyPublic);
00407 
00408     // we don't want to modify the vobject with pilot info, because it has
00409     // already been  modified on the desktop.  The VObject's modified state
00410     // overrides the PilotRec's modified state.
00411     // TODO: Also include this in the vcal conduit!!!
00412 //  if (e->syncStatus() != KCal::Incidence::SYNCNONE) return e;
00413 
00414     // otherwise, the vObject hasn't been touched.  Updated it with the
00415     // info from the PilotRec.
00416     if (de->getIndefinite()) {
00417         e->setHasDueDate(false);
00418     } else {
00419         e->setDtDue(readTm(de->getDueDate()));
00420         e->setHasDueDate(true);
00421     }
00422 
00423     // Categories
00424     // TODO: Sync categories
00425     // first remove all categories and then add only the appropriate one
00426     setCategory(e, de);
00427 
00428     // PRIORITY //
00429     e->setPriority(de->getPriority());
00430 
00431     // COMPLETED? //
00432     e->setCompleted(de->getComplete());
00433 
00434     e->setSummary(de->getDescription());
00435     e->setDescription(de->getNote());
00436 
00437     e->setSyncStatus(KCal::Incidence::SYNCNONE);
00438 
00439     return e;
00440 }
00441 
00442 
00443 
00444 void TodoConduit::setCategory(KCal::Todo *e, const PilotTodoEntry *de)
00445 {
00446     if (!e || !de) return;
00447     QStringList cats=e->categories();
00448     int cat=de->getCat();
00449     if (0<cat && cat<=15)
00450     {
00451         QString newcat=PilotAppCategory::codec()->toUnicode(fTodoAppInfo.category.name[cat]);
00452         if (!cats.contains(newcat))
00453         {
00454             cats.append( newcat );
00455             e->setCategories(cats);
00456         }
00457     }
00458 }
KDE Logo
This file is part of the documentation for kpilot Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:36:50 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003