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 Wed Jul 28 23:57:49 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003