|
|
|
/* Todo-Conduit for syncing KPilot and KOrganizer
|
|
|
|
**
|
|
|
|
** Copyright (C) 2002-2003 Reinhold Kainhofer
|
|
|
|
** Copyright (C) 1998-2001 Dan Pilone
|
|
|
|
** Copyright (C) 1998-2000 Preston Brown <pbrown@kde.org>
|
|
|
|
** Copyright (C) 1998 Herwin-Jan Steehouwer
|
|
|
|
** Copyright (C) 2001 Cornelius Schumacher
|
|
|
|
**
|
|
|
|
** This file is part of the todo conduit, a conduit for KPilot that
|
|
|
|
** synchronises the Pilot's todo application with the outside world,
|
|
|
|
** which currently means KOrganizer.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
** This program is free software; you can redistribute it and/or modify
|
|
|
|
** it under the terms of the GNU General Public License as published by
|
|
|
|
** the Free Software Foundation; either version 2 of the License, or
|
|
|
|
** (at your option) any later version.
|
|
|
|
**
|
|
|
|
** This program is distributed in the hope that it will be useful,
|
|
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
** GNU General Public License for more details.
|
|
|
|
**
|
|
|
|
** You should have received a copy of the GNU General Public License
|
|
|
|
** along with this program in a file called COPYING; if not, write to
|
|
|
|
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
** MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
** Bug reports and questions can be sent to kde-pim@kde.org
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "options.h"
|
|
|
|
|
|
|
|
#include <tqdatetime.h>
|
|
|
|
#include <textcodec.h>
|
|
|
|
|
|
|
|
#include <libkcal/calendar.h>
|
|
|
|
#include <libkcal/todo.h>
|
|
|
|
|
|
|
|
#include <pilotLocalDatabase.h>
|
|
|
|
|
|
|
|
#include "todo-conduit.moc"
|
|
|
|
#include "vcalconduitSettings.h"
|
|
|
|
#include "todo-factory.h"
|
|
|
|
|
|
|
|
#include "kcalRecord.h"
|
|
|
|
#include "todoRecord.h"
|
|
|
|
|
|
|
|
// define conduit versions, one for the version when categories were synced for the first time, and the current version number
|
|
|
|
#define CONDUIT_VERSION_CATEGORYSYNC 10
|
|
|
|
#define CONDUIT_VERSION 10
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
{
|
|
|
|
unsigned long version_conduit_todo = Pilot::PLUGIN_API;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TodoConduitPrivate::TodoConduitPrivate(KCal::Calendar *b) :
|
|
|
|
VCalConduitPrivateBase(b)
|
|
|
|
{
|
|
|
|
fAllTodos.setAutoDelete(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TodoConduitPrivate::addIncidence(KCal::Incidence*e)
|
|
|
|
{
|
|
|
|
fAllTodos.append(static_cast<KCal::Todo*>(e));
|
|
|
|
fCalendar->addTodo(static_cast<KCal::Todo*>(e));
|
|
|
|
}
|
|
|
|
|
|
|
|
int TodoConduitPrivate::updateIncidences()
|
|
|
|
{
|
|
|
|
fAllTodos = fCalendar->todos();
|
|
|
|
fAllTodos.setAutoDelete(false);
|
|
|
|
return fAllTodos.count();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void TodoConduitPrivate::removeIncidence(KCal::Incidence *e)
|
|
|
|
{
|
|
|
|
fAllTodos.remove(static_cast<KCal::Todo*>(e));
|
|
|
|
if (!fCalendar) return;
|
|
|
|
fCalendar->deleteTodo(static_cast<KCal::Todo*>(e));
|
|
|
|
// now just in case we're in the middle of reading through our list
|
|
|
|
// and we delete something, set reading to false so we start at the
|
|
|
|
// top again next time and don't have problems with our iterator
|
|
|
|
reading = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KCal::Incidence *TodoConduitPrivate::findIncidence(recordid_t id)
|
|
|
|
{
|
|
|
|
KCal::Todo::List::ConstIterator it;
|
|
|
|
for( it = fAllTodos.begin(); it != fAllTodos.end(); ++it ) {
|
|
|
|
KCal::Todo *todo = *it;
|
|
|
|
if ((recordid_t)(todo->pilotId()) == id) return todo;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KCal::Incidence *TodoConduitPrivate::findIncidence(PilotRecordBase *tosearch)
|
|
|
|
{
|
|
|
|
PilotTodoEntry*entry=dynamic_cast<PilotTodoEntry*>(tosearch);
|
|
|
|
if (!entry) return 0L;
|
|
|
|
|
|
|
|
TQString title=entry->getDescription();
|
|
|
|
TQDateTime dt=readTm( entry->getDueDate() );
|
|
|
|
|
|
|
|
KCal::Todo::List::ConstIterator it;
|
|
|
|
for( it = fAllTodos.begin(); it != fAllTodos.end(); ++it ) {
|
|
|
|
KCal::Todo *event = *it;
|
|
|
|
if ( (event->dtDue().date() == dt.date()) && (event->summary() == title) ) return event;
|
|
|
|
}
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KCal::Incidence *TodoConduitPrivate::getNextIncidence()
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
if (reading) {
|
|
|
|
++fAllTodosIterator;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
reading=true;
|
|
|
|
fAllTodosIterator = fAllTodos.begin();
|
|
|
|
}
|
|
|
|
|
|
|
|
return(fAllTodosIterator == fAllTodos.end()) ? 0L : *fAllTodosIterator;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KCal::Incidence *TodoConduitPrivate::getNextModifiedIncidence()
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
KCal::Todo*e=0L;
|
|
|
|
if (!reading)
|
|
|
|
{
|
|
|
|
reading=true;
|
|
|
|
fAllTodosIterator = fAllTodos.begin();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
++fAllTodosIterator;
|
|
|
|
}
|
|
|
|
if ( fAllTodosIterator != fAllTodos.end() ) e=*fAllTodosIterator;
|
|
|
|
while (fAllTodosIterator != fAllTodos.end() &&
|
|
|
|
e && e->syncStatus()!=KCal::Incidence::SYNCMOD && e->pilotId())
|
|
|
|
{
|
|
|
|
e = (++fAllTodosIterator != fAllTodos.end()) ? *fAllTodosIterator : 0L;
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
if(e)
|
|
|
|
DEBUGKPILOT<< e->summary()<<" had SyncStatus="<<e->syncStatus()<<endl;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return (fAllTodosIterator == fAllTodos.end()) ? 0L : *fAllTodosIterator;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
* TodoConduit class *
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
TodoConduit::TodoConduit(KPilotLink *d,
|
|
|
|
const char *n,
|
|
|
|
const TQStringList &a) : VCalConduitBase(d,n,a),
|
|
|
|
fTodoAppInfo( 0L )
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
fConduitName=i18n("To-do");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TodoConduit::~TodoConduit()
|
|
|
|
{
|
|
|
|
// FUNCTIONSETUP;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TodoConduit::_setAppInfo()
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
// get the address application header information
|
|
|
|
|
|
|
|
if( !fTodoAppInfo )
|
|
|
|
{
|
|
|
|
DEBUGKPILOT << fname << ": fTodoAppInfo is NULL" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( !fDatabase )
|
|
|
|
{
|
|
|
|
DEBUGKPILOT << fname << ": fDatabase is NULL" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fTodoAppInfo->writeTo(fDatabase);
|
|
|
|
}
|
|
|
|
|
|
|
|
void TodoConduit::_getAppInfo()
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
// get the address application header information
|
|
|
|
|
|
|
|
KPILOT_DELETE( fTodoAppInfo );
|
|
|
|
fTodoAppInfo = new PilotToDoInfo(fDatabase);
|
|
|
|
fTodoAppInfo->dump();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const TQString TodoConduit::getTitle(PilotRecordBase *de)
|
|
|
|
{
|
|
|
|
PilotTodoEntry*d=dynamic_cast<PilotTodoEntry*>(de);
|
|
|
|
if (d)
|
|
|
|
{
|
|
|
|
return TQString(d->getDescription());
|
|
|
|
}
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TodoConduit::readConfig()
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
VCalConduitBase::readConfig();
|
|
|
|
// determine if the categories have ever been synce. Needed to prevent loosing
|
|
|
|
// the categories on the desktop. Also use a full sync for the first time to
|
|
|
|
// make sure the palm categories are really transferred to the desktop.
|
|
|
|
//
|
|
|
|
categoriesSynced = config()->conduitVersion()>=CONDUIT_VERSION_CATEGORYSYNC;
|
|
|
|
if (!categoriesSynced && !isFullSync() )
|
|
|
|
{
|
|
|
|
changeSync(SyncMode::eFullSync);
|
|
|
|
}
|
|
|
|
DEBUGKPILOT<<"categoriesSynced=" << categoriesSynced << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void TodoConduit::preSync()
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
VCalConduitBase::preSync();
|
|
|
|
_getAppInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
void TodoConduit::postSync()
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
VCalConduitBase::postSync();
|
|
|
|
// after this successful sync the categories have been synced for sure
|
|
|
|
config()->setConduitVersion( CONDUIT_VERSION );
|
|
|
|
config()->writeConfig();
|
|
|
|
_setAppInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PilotRecord *TodoConduit::recordFromIncidence(PilotRecordBase *de, const KCal::Incidence *e)
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
|
|
|
|
if (!de || !e)
|
|
|
|
{
|
|
|
|
DEBUGKPILOT << fname
|
|
|
|
<< ": got NULL entry or NULL incidence." << endl;
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
PilotTodoEntry *todoEntry = dynamic_cast<PilotTodoEntry*>(de);
|
|
|
|
if (!todoEntry)
|
|
|
|
{
|
|
|
|
// Secretly wasn't a todo entry after all
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
const KCal::Todo *todo = dynamic_cast<const KCal::Todo *>(e);
|
|
|
|
if (!todo)
|
|
|
|
{
|
|
|
|
DEBUGKPILOT << fname << ": Incidence is not a todo." << endl;
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
// don't need to check for null pointers here, the recordFromIncidence(PTE*, KCal::Todo*) will do that.
|
|
|
|
if (KCalSync::setTodoEntry(todoEntry,todo,*fTodoAppInfo->categoryInfo()))
|
|
|
|
{
|
|
|
|
return todoEntry->pack();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KCal::Incidence *TodoConduit::incidenceFromRecord(KCal::Incidence *e, const PilotRecordBase *de)
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
|
|
|
|
if (!de || !e)
|
|
|
|
{
|
|
|
|
DEBUGKPILOT << fname
|
|
|
|
<< ": Got NULL entry or NULL incidence." << endl;
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
const PilotTodoEntry *todoEntry = dynamic_cast<const PilotTodoEntry *>(de);
|
|
|
|
if (!todoEntry)
|
|
|
|
{
|
|
|
|
DEBUGKPILOT << fname << ": HH record not a todo entry." << endl;
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
KCal::Todo *todo = dynamic_cast<KCal::Todo *>(e);
|
|
|
|
if (!todo)
|
|
|
|
{
|
|
|
|
DEBUGKPILOT << fname << ": Incidence is not a todo." << endl;
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
KCalSync::setTodo(todo, todoEntry,*fTodoAppInfo->categoryInfo());
|
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void TodoConduit::preRecord(PilotRecord*r)
|
|
|
|
{
|
|
|
|
FUNCTIONSETUP;
|
|
|
|
if (!categoriesSynced && r)
|
|
|
|
{
|
|
|
|
const PilotRecordBase *de = newPilotEntry(r);
|
|
|
|
KCal::Incidence *e = fP->findIncidence(r->id());
|
|
|
|
KCalSync::setCategory(dynamic_cast<KCal::Todo*>(e),
|
|
|
|
dynamic_cast<const PilotTodoEntry*>(de),
|
|
|
|
*fTodoAppInfo->categoryInfo());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static VCalConduitSettings *config_vcal = 0L;
|
|
|
|
|
|
|
|
VCalConduitSettings *TodoConduit::theConfig() {
|
|
|
|
if (!config_vcal)
|
|
|
|
{
|
|
|
|
config_vcal = new VCalConduitSettings(CSL1("Calendar"));
|
|
|
|
}
|
|
|
|
|
|
|
|
return config_vcal;
|
|
|
|
}
|
|
|
|
|
|
|
|
VCalConduitSettings *TodoConduit::config() {
|
|
|
|
return theConfig();
|
|
|
|
}
|