kpilot

todo-conduit.cc

Go to the documentation of this file.
00001 /* 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 <pbrown@kde.org>
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., 51 Franklin Street, Fifth Floor, Boston,
00028 ** MA 02110-1301, USA.
00029 */
00030 
00031 /*
00032 ** Bug reports and questions can be sent to kde-pim@kde.org
00033 */
00034 
00035 #include "options.h"
00036 
00037 #include <qdatetime.h>
00038 #include <qtextcodec.h>
00039 
00040 #include <libkcal/calendar.h>
00041 #include <libkcal/todo.h>
00042 
00043 #include <pilotLocalDatabase.h>
00044 
00045 #include "todo-conduit.moc"
00046 #include "vcalconduitSettings.h"
00047 #include "todo-factory.h"
00048 
00049 #include "kcalRecord.h"
00050 #include "todoRecord.h"
00051 
00052 // define conduit versions, one for the version when categories were synced for the first time, and the current version number
00053 #define CONDUIT_VERSION_CATEGORYSYNC 10
00054 #define CONDUIT_VERSION 10
00055 
00056 extern "C"
00057 {
00058 unsigned long version_conduit_todo = Pilot::PLUGIN_API;
00059 }
00060 
00061 
00062 TodoConduitPrivate::TodoConduitPrivate(KCal::Calendar *b) :
00063     VCalConduitPrivateBase(b)
00064 {
00065     fAllTodos.setAutoDelete(false);
00066 }
00067 
00068 void TodoConduitPrivate::addIncidence(KCal::Incidence*e)
00069 {
00070     fAllTodos.append(static_cast<KCal::Todo*>(e));
00071     fCalendar->addTodo(static_cast<KCal::Todo*>(e));
00072 }
00073 
00074 int TodoConduitPrivate::updateIncidences()
00075 {
00076     fAllTodos = fCalendar->todos();
00077     fAllTodos.setAutoDelete(false);
00078     return fAllTodos.count();
00079 }
00080 
00081 
00082 void TodoConduitPrivate::removeIncidence(KCal::Incidence *e)
00083 {
00084     fAllTodos.remove(static_cast<KCal::Todo*>(e));
00085     if (!fCalendar) return;
00086     fCalendar->deleteTodo(static_cast<KCal::Todo*>(e));
00087     // now just in case we're in the middle of reading through our list
00088     // and we delete something, set reading to false so we start at the
00089     // top again next time and don't have problems with our iterator
00090     reading = false;
00091 }
00092 
00093 
00094 
00095 KCal::Incidence *TodoConduitPrivate::findIncidence(recordid_t id)
00096 {
00097     KCal::Todo::List::ConstIterator it;
00098         for( it = fAllTodos.begin(); it != fAllTodos.end(); ++it ) {
00099                 KCal::Todo *todo = *it;
00100         if ((recordid_t)(todo->pilotId()) == id) return todo;
00101     }
00102 
00103     return 0L;
00104 }
00105 
00106 
00107 
00108 KCal::Incidence *TodoConduitPrivate::findIncidence(PilotRecordBase *tosearch)
00109 {
00110     PilotTodoEntry*entry=dynamic_cast<PilotTodoEntry*>(tosearch);
00111     if (!entry) return 0L;
00112 
00113     QString title=entry->getDescription();
00114     QDateTime dt=readTm( entry->getDueDate() );
00115 
00116     KCal::Todo::List::ConstIterator it;
00117         for( it = fAllTodos.begin(); it != fAllTodos.end(); ++it ) {
00118                 KCal::Todo *event = *it;
00119         if ( (event->dtDue().date() == dt.date()) && (event->summary() == title) ) return event;
00120     }
00121     return 0L;
00122 }
00123 
00124 
00125 
00126 KCal::Incidence *TodoConduitPrivate::getNextIncidence()
00127 {
00128     FUNCTIONSETUP;
00129     if (reading) {
00130         ++fAllTodosIterator;
00131     }
00132     else {
00133         reading=true;
00134         fAllTodosIterator = fAllTodos.begin();
00135     }
00136 
00137     return(fAllTodosIterator == fAllTodos.end()) ? 0L : *fAllTodosIterator;
00138 }
00139 
00140 
00141 
00142 KCal::Incidence *TodoConduitPrivate::getNextModifiedIncidence()
00143 {
00144     FUNCTIONSETUP;
00145     KCal::Todo*e=0L;
00146     if (!reading)
00147     {
00148         reading=true;
00149         fAllTodosIterator = fAllTodos.begin();
00150     }
00151     else
00152     {
00153         ++fAllTodosIterator;
00154     }
00155     if ( fAllTodosIterator != fAllTodos.end() ) e=*fAllTodosIterator;
00156     while (fAllTodosIterator != fAllTodos.end() &&
00157         e && e->syncStatus()!=KCal::Incidence::SYNCMOD && e->pilotId())
00158     {
00159         e = (++fAllTodosIterator != fAllTodos.end()) ? *fAllTodosIterator : 0L;
00160 
00161 #ifdef DEBUG
00162     if(e)
00163         DEBUGKPILOT<< e->summary()<<" had SyncStatus="<<e->syncStatus()<<endl;
00164 #endif
00165 
00166     }
00167 
00168     return (fAllTodosIterator == fAllTodos.end()) ? 0L : *fAllTodosIterator;
00169 }
00170 
00171 
00172 
00173 /****************************************************************************
00174  *                          TodoConduit class                               *
00175  ****************************************************************************/
00176 
00177 TodoConduit::TodoConduit(KPilotLink *d,
00178     const char *n,
00179     const QStringList &a) : VCalConduitBase(d,n,a),
00180     fTodoAppInfo( 0L )
00181 {
00182     FUNCTIONSETUP;
00183     fConduitName=i18n("To-do");
00184 }
00185 
00186 
00187 
00188 TodoConduit::~TodoConduit()
00189 {
00190 //  FUNCTIONSETUP;
00191 }
00192 
00193 
00194 
00195 void TodoConduit::_setAppInfo()
00196 {
00197     FUNCTIONSETUP;
00198     // get the address application header information
00199 
00200     if( !fTodoAppInfo )
00201     {
00202         DEBUGKPILOT << fname << ": fTodoAppInfo is NULL" << endl;
00203         return;
00204     }
00205     if( !fDatabase )
00206     {
00207         DEBUGKPILOT << fname << ": fDatabase is NULL" << endl;
00208         return;
00209     }
00210 
00211     fTodoAppInfo->writeTo(fDatabase);
00212 }
00213 
00214 void TodoConduit::_getAppInfo()
00215 {
00216     FUNCTIONSETUP;
00217     // get the address application header information
00218 
00219     KPILOT_DELETE( fTodoAppInfo );
00220     fTodoAppInfo = new PilotToDoInfo(fDatabase);
00221     fTodoAppInfo->dump();
00222 }
00223 
00224 
00225 
00226 const QString TodoConduit::getTitle(PilotRecordBase *de)
00227 {
00228     PilotTodoEntry*d=dynamic_cast<PilotTodoEntry*>(de);
00229     if (d)
00230     {
00231         return QString(d->getDescription());
00232     }
00233     return QString::null;
00234 }
00235 
00236 
00237 
00238 void TodoConduit::readConfig()
00239 {
00240     FUNCTIONSETUP;
00241     VCalConduitBase::readConfig();
00242     // determine if the categories have ever been synce. Needed to prevent loosing
00243     // the categories on the desktop. Also use a full sync for the first time to
00244     // make sure the palm categories are really transferred to the desktop.
00245     //
00246     categoriesSynced = config()->conduitVersion()>=CONDUIT_VERSION_CATEGORYSYNC;
00247     if (!categoriesSynced && !isFullSync() )
00248     {
00249         changeSync(SyncMode::eFullSync);
00250     }
00251     DEBUGKPILOT<<"categoriesSynced=" << categoriesSynced << endl;
00252 }
00253 
00254 void TodoConduit::preSync()
00255 {
00256     FUNCTIONSETUP;
00257     VCalConduitBase::preSync();
00258     _getAppInfo();
00259 }
00260 
00261 void TodoConduit::postSync()
00262 {
00263     FUNCTIONSETUP;
00264     VCalConduitBase::postSync();
00265     // after this successful sync the categories have been synced for sure
00266     config()->setConduitVersion( CONDUIT_VERSION );
00267     config()->writeConfig();
00268     _setAppInfo();
00269 }
00270 
00271 
00272 
00273 PilotRecord *TodoConduit::recordFromIncidence(PilotRecordBase *de, const KCal::Incidence *e)
00274 {
00275     FUNCTIONSETUP;
00276 
00277     if (!de || !e)
00278     {
00279         DEBUGKPILOT << fname
00280             << ": got NULL entry or NULL incidence." << endl;
00281         return 0L;
00282     }
00283 
00284     PilotTodoEntry *todoEntry = dynamic_cast<PilotTodoEntry*>(de);
00285     if (!todoEntry)
00286     {
00287         // Secretly wasn't a todo entry after all
00288         return 0L;
00289     }
00290 
00291     const KCal::Todo *todo = dynamic_cast<const KCal::Todo *>(e);
00292     if (!todo)
00293     {
00294         DEBUGKPILOT << fname << ": Incidence is not a todo." << endl;
00295         return 0L;
00296     }
00297 
00298     // don't need to check for null pointers here, the recordFromIncidence(PTE*, KCal::Todo*) will do that.
00299     if (KCalSync::setTodoEntry(todoEntry,todo,*fTodoAppInfo->categoryInfo()))
00300     {
00301         return todoEntry->pack();
00302     }
00303     else
00304     {
00305         return 0L;
00306     }
00307 }
00308 
00309 KCal::Incidence *TodoConduit::incidenceFromRecord(KCal::Incidence *e, const PilotRecordBase *de)
00310 {
00311     FUNCTIONSETUP;
00312 
00313     if (!de || !e)
00314     {
00315         DEBUGKPILOT << fname
00316             << ": Got NULL entry or NULL incidence." << endl;
00317         return 0L;
00318     }
00319 
00320     const PilotTodoEntry *todoEntry = dynamic_cast<const PilotTodoEntry *>(de);
00321     if (!todoEntry)
00322     {
00323         DEBUGKPILOT << fname << ": HH record not a todo entry." << endl;
00324         return 0L;
00325     }
00326 
00327     KCal::Todo *todo = dynamic_cast<KCal::Todo *>(e);
00328     if (!todo)
00329     {
00330         DEBUGKPILOT << fname << ": Incidence is not a todo." << endl;
00331         return 0L;
00332     }
00333 
00334     KCalSync::setTodo(todo, todoEntry,*fTodoAppInfo->categoryInfo());
00335     return e;
00336 }
00337 
00338 
00339 
00340 
00341 
00342 void TodoConduit::preRecord(PilotRecord*r)
00343 {
00344     FUNCTIONSETUP;
00345     if (!categoriesSynced && r)
00346     {
00347         const PilotRecordBase *de = newPilotEntry(r);
00348         KCal::Incidence *e = fP->findIncidence(r->id());
00349         KCalSync::setCategory(dynamic_cast<KCal::Todo*>(e),
00350             dynamic_cast<const PilotTodoEntry*>(de),
00351             *fTodoAppInfo->categoryInfo());
00352     }
00353 }
00354 
00355 
00356 
00357 
00358 
00359 
00360 static VCalConduitSettings *config_vcal = 0L;
00361 
00362 VCalConduitSettings *TodoConduit::theConfig() {
00363     if (!config_vcal)
00364     {
00365         config_vcal = new VCalConduitSettings(CSL1("Calendar"));
00366     }
00367 
00368     return config_vcal;
00369 }
00370 
00371 VCalConduitSettings *TodoConduit::config() {
00372     return theConfig();
00373 }