diff options
Diffstat (limited to 'kpilot/conduits/vcalconduit/vcal-conduitbase.cc')
-rw-r--r-- | kpilot/conduits/vcalconduit/vcal-conduitbase.cc | 622 |
1 files changed, 0 insertions, 622 deletions
diff --git a/kpilot/conduits/vcalconduit/vcal-conduitbase.cc b/kpilot/conduits/vcalconduit/vcal-conduitbase.cc deleted file mode 100644 index cd288ba59..000000000 --- a/kpilot/conduits/vcalconduit/vcal-conduitbase.cc +++ /dev/null @@ -1,622 +0,0 @@ -/* KPilot -** -** Copyright (C) 2002-3 by Reinhold Kainhofer -** Copyright (C) 2001 by Dan Pilone -** -** Contributions: -** Copyright (c) 2001 David Jarvie <software@astrojar.org.uk> -** Copyright (C) 2006 by Bertjan Broeksema <b.broeksema@gmail.com> -** -** This file defines the vcal-conduit plugin. -*/ - -/* -** 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 <tqtimer.h> -#include <tqfile.h> - -#include <kmessagebox.h> -#include <kio/netaccess.h> - -#include "libkcal/calendar.h" -#include "libkcal/calendarlocal.h" -#include "libkcal/calendarresources.h" -#include <kstandarddirs.h> - -#include "pilotSerialDatabase.h" -#include "pilotLocalDatabase.h" -#include "pilotDateEntry.h" - -#include "vcal-conduitbase.moc" -#include "vcalconduitSettings.h" - -#ifndef LIBKCAL_IS_VERSION -#warning "Using an old version of libkcal with timezone bug." -#define LIBKCAL_IS_VERSION(a,b,c) (0) -#endif - -#include "conduitstate.h" -#include "initstate.h" - - -/**************************************************************************** - * VCalConduitBase class * - ****************************************************************************/ - -VCalConduitBase::VCalConduitBase(KPilotLink *d, - const char *n, - const TQStringList &a) : - ConduitAction(d,n,a), - fCalendar(0L), - fP(0L) -{ - FUNCTIONSETUP; - - fState = new InitState(); -} - -VCalConduitBase::~VCalConduitBase() -{ - FUNCTIONSETUP; - - KPILOT_DELETE(fP); - KPILOT_DELETE(fState); - KPILOT_DELETE(fCalendar); - KPILOT_DELETE(fDatabase); - KPILOT_DELETE(fLocalDatabase); -} - - -/* - There are several different scenarios for a record on the Palm and its PC - counterpart. N means a new record, M flags a modified record, D a deleted - and - an unmodified record. First is the Palm record, second the - corresponding PC record: - (-,-) unchanged, just sync if first time or full sync - (N,-) no rec matching the Palm ID in the backupDB/calendar yet => add - KCal::Event - (M,-) record is in backupDB, unchanged in calendar => modify in calendar and - in backupDB - (D,-) deleted on Palm, exists in backupDB and calendar => just delete from - calendar and backupDB - (-,N) no or invalid pilotID set for the KCal::Event => just add to palm and - backupDB - (-,M) valid PilotID set => just modify on Palm - (-,D) Record in backupDB, but not in calendar => delete from Palm and - backupDB - (N,N) Can't find out (the two records are not correlated in any way, they - just have the same data!! - (M,M),(M,L),(L,M) (Record exists on Palm and the Event has the ID) CONFLICT, - ask the user what to do or use a config setting - (L,L) already deleted on both, no need to do anything. - - The sync process is as follows (for a fast sync): - 1) HHToPCState goes through all records on Palm (just the modified one - are necessary), find it in the backupDB. The following handles ([NMD],*) - a) if it doesn't exist and was not deleted, add it to the calendar and - the backupDB - b) if it exists, is unchanged in the calendar and was not deleted, - just modify in the calendar - c) if it exists and was deleted, delete it from the calendar if - necessary - 2) PCToHHState goes through all KCale::Events in the calendar (just - modified, this is the modification time is later than the last sync time - ). This handles (-,N),(-,M) - a) if it does not have a pilotID, add it to the palm and backupDB, - store the PalmID - b) if it has a valid pilotID, update the Palm record and the backup - 3) DeletedUnsyncedHHState goes through all palm records (which don't - have the deleted flag) of the palm db and if one does not exist in the - Calendar, it was deleted there, so delete it from the Palm and backup, - too. This handles the case of (-,D) - 4) DeletedUnsyncedPCState goes through all KCal::Events in the calendar and - looks for a corresponding event in the palm database. If it does not - exist, that means that it was deleted on the palm, so we need to also - delete it from the local calendar. This handles the case of (D,-). - - In addition to the fast sync, where the last sync was done with this very - PC and calendar file, there are two special cases: a full and a first sync. - -) a full sync goes through all records, not just the modified ones. The - pilotID setting of the calendar records is used to determine if the - record already exists. if yes, the record is just modified. - -) a first sync completely ignores the pilotID setting of the calendar - events. All records are added, so there might be duplicates. The add - function for the calendar should check if a similar record already - exists, but this is not done yet. - - -) a full sync is done if - a) there is a backupdb and a calendar, but the PC id number changed - b) it was explicitly requested by pressing the full sync button in KPilot - c) the setting "always full sync" was selected in the configuration dlg - -) a first sync is done if - a) either the calendar or the backup DB does not exist. - b) the calendar and the backup DB exists, but the sync is done for a - different User name - c) it was explicitly requested in KPilot -*/ - -/* virtual */ bool VCalConduitBase::exec() -{ - FUNCTIONSETUP; - - readConfig(); - - // don't do a first sync by default in any case, only when explicitly - // requested, or the backup database or the alendar are empty. - setFirstSync( false ); - - // TODO: Check Full sync and First sync - bool retrieved = false; - if ( !openDatabases( dbname(), &retrieved ) ) goto error; - setFirstSync( retrieved ); - - // If we are in testmode we don't need the local calendar. Else a - // calendar *must* be opened, we want to sync something don't we? - if (!syncMode().isTest() && !openCalendar() ) goto error; - - // Start processing the sync - TQTimer::singleShot(0, this, TQT_SLOT(slotProcess())); - return true; - -error: - emit logError( i18n( "Could not open the calendar databases." ) ); - - KPILOT_DELETE(fCalendar); - KPILOT_DELETE(fP); - KPILOT_DELETE(fState); - return false; -} - -void VCalConduitBase::slotProcess() { - FUNCTIONSETUP; - - // start the current state if necessary - if( fState && !fState->started() ) { - fState->startSync( this ); - } - - // Process next record if applicable - if( hasNextRecord ) - { - fState->handleRecord( this ); - TQTimer::singleShot( 0, this, TQT_SLOT( slotProcess() ) ); - } - // Else finish the current state if there is one - else if( fState ) - { - fState->finishSync( this ); - TQTimer::singleShot( 0, this, TQT_SLOT( slotProcess() ) ); - } - // No state so sync is finished - else - { - DEBUGKPILOT << fname << ": Sync finished." << endl; - delayDone(); - } -} - -/* virtual */ void VCalConduitBase::readConfig() -{ - config()->readConfig(); - SyncAction::ConflictResolution res = (SyncAction::ConflictResolution) - (config()->conflictResolution()); - setConflictResolution( res ); -} - -static void listResources( KCal::CalendarResources *p ) -{ - FUNCTIONSETUP; - KCal::CalendarResourceManager *manager = p->resourceManager(); - - DEBUGKPILOT << fname << ": Resources in calendar:" << endl; - KCal::CalendarResourceManager::Iterator it; - for( it = manager->begin(); it != manager->end(); ++it ) - { - DEBUGKPILOT << fname << ": " << (*it)->resourceName() << endl; - } -} - -/* virtual */ bool VCalConduitBase::openCalendar() -{ - FUNCTIONSETUP; - - KConfig korgcfg( locate( "config", CSL1("korganizerrc") ) ); - - // this part taken from adcalendarbase.cpp: - korgcfg.setGroup( "Time & Date" ); - TQString tz(korgcfg.readEntry( "TimeZoneId" ) ); - - DEBUGKPILOT << fname << ": KOrganizer's time zone = " << tz << endl; - - // Need a subclass ptr. for the ResourceCalendar methods - KCal::CalendarResources *rescal = 0L; - - DEBUGKPILOT << fname << ": Got calendar type " << config()->calendarType() - << endl; - - switch(config()->calendarType()) - { - case VCalConduitSettings::eCalendarLocal: - { - DEBUGKPILOT << fname << "Using CalendarLocal, file = " - << config()->calendarFile() << endl; - - if ( config()->calendarFile().isEmpty() ) - { - DEBUGKPILOT << fname << "Empty calendar file name." << endl; - - emit logError( i18n( "You selected to sync with an iCalendar" - " file, but did not give a filename. Please select a" - " valid file name in the conduit's configuration" - " dialog" ) ); - return false; - } - - fCalendar = new KCal::CalendarLocal( tz ); - if ( !fCalendar ) - { - WARNINGKPILOT - << "Cannot initialize calendar object for file " - << config()->calendarFile() << endl; - return false; - } - - DEBUGKPILOT << fname << "Calendar's timezone: " - << fCalendar->timeZoneId() << endl; - DEBUGKPILOT << fname << "Calendar is local time: " - << fCalendar->isLocalTime() << endl; - - emit logMessage( fCalendar->isLocalTime() ? - i18n( "Using local time zone: %1" ).arg( tz ) : - i18n( "Using non-local time zone: %1" ).arg( tz ) ); - - KURL kurl( config()->calendarFile() ); - if( !KIO::NetAccess::download( config()->calendarFile(), - fCalendarFile, 0L ) && !kurl.isLocalFile() ) - { - emit logError(i18n( "You chose to sync with the file \"%1\", which " - "cannot be opened. Please make sure to supply a " - "valid file name in the conduit's configuration dialog. " - "Aborting the conduit." ).arg( config()->calendarFile() ) ); - KIO::NetAccess::removeTempFile( fCalendarFile ); - return false; - } - - // if there is no calendar yet, use a first sync.. - // the calendar is initialized, so nothing more to do... - if (!dynamic_cast<KCal::CalendarLocal*>(fCalendar)->load(fCalendarFile) ) - { - DEBUGKPILOT << fname << "Calendar file " << fCalendarFile - << " could not be opened. Will create a new one" << endl; - - // Try to create empty file. if it fails, - // no valid file name was given. - TQFile fl(fCalendarFile); - if (!fl.open(IO_WriteOnly | IO_Append)) - { - DEBUGKPILOT << fname << "Invalid calendar file name " - << fCalendarFile << endl; - - emit logError( i18n( "You chose to sync with the file \"%1\", which " - "cannot be opened or created. Please make sure to supply a " - "valid file name in the conduit's configuration dialog. " - "Aborting the conduit." ).arg( config()->calendarFile() ) ); - return false; - } - fl.close(); - setFirstSync( true ); - } - addSyncLogEntry( i18n( "Syncing with file \"%1\"" ) - .arg( config()->calendarFile() ) ); - break; - } - - case VCalConduitSettings::eCalendarResource: - DEBUGKPILOT << "Using CalendarResource!" << endl; - - rescal = new KCal::CalendarResources( tz ); - listResources(rescal); - fCalendar = rescal; - if ( !fCalendar) - { - WARNINGKPILOT << "Cannot initialize calendar " << - "object for ResourceCalendar" << endl; - return false; - } - -#if LIBKCAL_IS_VERSION(1,1,0) - rescal->readConfig(); - rescal->load(); -#else -#warning "Timezone bug is present." -#endif - addSyncLogEntry( i18n( "Syncing with standard calendar resource." ) ); - emit logMessage( fCalendar->isLocalTime() ? - i18n( "Using local time zone: %1" ).arg( tz ) : - i18n( "Using non-local time zone: %1" ).arg( tz ) ); - break; - default: - break; - } - - if ( !fCalendar ) - { - WARNINGKPILOT << "Unable to initialize calendar object." - << " Please check the conduit's setup." << endl; - emit logError( i18n( "Unable to initialize the calendar object. Please" - " check the conduit's setup") ); - return false; - } - fP = createPrivateCalendarData( fCalendar ); - if ( !fP ) - { - return false; - } - int rc = fP->updateIncidences(); - DEBUGKPILOT << fname << ": return from updateIncidences: [" << rc - << "]" << endl; - - if ( fP->count() < 1 ) - { - setFirstSync( true ); - } - - return true; -} - -KCal::Incidence* VCalConduitBase::addRecord( PilotRecord *r ) -{ - FUNCTIONSETUP; - - recordid_t id = fLocalDatabase->writeRecord( r ); - DEBUGKPILOT<<fname<<": Pilot Record ID = " << r->id() << ", backup ID = " - << id << endl; - - PilotRecordBase *de = newPilotEntry( r ); - KCal::Incidence*e = 0L; - - if ( de ) - { - e = fP->findIncidence( r->id() ); - if ( !e ) - { - // no corresponding entry found, so create, copy and insert it. - e = newIncidence(); - incidenceFromRecord( e, de ); - fP->addIncidence( e ); - fCtrPC->created(); - } - else - { - // similar entry found, so just copy, no need to insert again - incidenceFromRecord( e, de ); - fCtrPC->updated(); - } - } - KPILOT_DELETE( de ); - return e; -} - -int VCalConduitBase::resolveConflict( KCal::Incidence *e, PilotRecordBase *de ) { - if ( getConflictResolution() == SyncAction::eAskUser ) - { - // TODO: This is messed up!!! - TQString query = i18n( "The following item was modified " - "both on the Handheld and on your PC:\nPC entry:\n\t" ); - query += e->summary(); - query += i18n( "\nHandheld entry:\n\t" ); - query += getTitle( de ); - query += i18n( "\n\nWhich entry do you want to keep? It will " - "overwrite the other entry." ); - - return KMessageBox::No == questionYesNo( - query, - i18n( "Conflicting Entries" ), - TQString::null, - 0 /* Never timeout */, - i18n( "Handheld" ), i18n( "PC" )); - } - return getConflictResolution(); -} - -KCal::Incidence*VCalConduitBase::changeRecord(PilotRecord *r,PilotRecord *) -{ - FUNCTIONSETUP; - - PilotRecordBase *de = newPilotEntry( r ); - KCal::Incidence *e = fP->findIncidence( r->id() ); - - DEBUGKPILOT << fname << ": Pilot Record ID: [" << r->id() << "]" << endl; - - if ( e && de ) - { - // TODO: check for conflict, and if there is one, ask for resolution - if ( ( e->syncStatus() != KCal::Incidence::SYNCNONE ) - && r->isModified() ) - { - // TODO: I have not yet found a way to complete ignore an item - if (resolveConflict( e, de ) ) - { - // PC record takes precedence: - KPILOT_DELETE( de ); - return e; - } - } - // no conflict or conflict resolution says, Palm overwrites, so do it: - incidenceFromRecord( e, de ); - - // NOTE: This MUST be done last, since every other set* call - // calls updated(), which will trigger an - // setSyncStatus(SYNCMOD)!!! - e->setSyncStatus(KCal::Incidence::SYNCNONE); - fLocalDatabase->writeRecord( r ); - } - else - { - WARNINGKPILOT - << "While changing record -- not found in iCalendar" << endl; - addRecord( r ); - } - - KPILOT_DELETE( de ); - return e; -} - - -KCal::Incidence*VCalConduitBase::deleteRecord( PilotRecord *r, PilotRecord * ) -{ - FUNCTIONSETUP; - - KCal::Incidence *e = fP->findIncidence(r->id()); - if (e) - { - // RemoveEvent also takes it out of the calendar. - fP->removeIncidence(e); - fCtrPC->deleted(); - } - fLocalDatabase->writeRecord( r ); - return NULL; -} - - -void VCalConduitBase::addPalmRecord( KCal::Incidence *e ) -{ - FUNCTIONSETUP; - - PilotRecordBase *de = newPilotEntry( 0L ); - updateIncidenceOnPalm( e, de ); - fCtrHH->created(); - KPILOT_DELETE( de ); -} - - -void VCalConduitBase::changePalmRecord(KCal::Incidence*e, PilotRecord*s) -{ - PilotRecordBase *de = newPilotEntry( s ); - updateIncidenceOnPalm( e, de ); - fCtrHH->updated(); - KPILOT_DELETE( de ); -} - - -void VCalConduitBase::deletePalmRecord( KCal::Incidence *e, PilotRecord *s ) -{ - FUNCTIONSETUP; - if ( s ) - { - DEBUGKPILOT << fname << ": deleting record " << s->id() << endl; - s->setDeleted(); - fDatabase->writeRecord( s ); - fLocalDatabase->writeRecord( s ); - fCtrHH->deleted(); - } - else - { - DEBUGKPILOT << fname << ": could not find record to delete ("; - DEBUGKPILOT << e->pilotId() << ")" << endl; - } - - Q_UNUSED(e); -} - -/* I have to use a pointer to an existing PilotDateEntry so that I can handle - new records as well (and to prevent some crashes concerning the validity - domain of the PilotRecord*r). In syncEvent this PilotDateEntry is created. */ -void VCalConduitBase::updateIncidenceOnPalm( KCal::Incidence *e, - PilotRecordBase *de ) -{ - FUNCTIONSETUP; - if ( !de || !e ) { - DEBUGKPILOT << fname << ": NULL event given... Skipping it" << endl; - return; - } - - if ( e->syncStatus() == KCal::Incidence::SYNCDEL ) - { - DEBUGKPILOT << fname << ": don't write deleted incidence " - << e->summary() << " to the palm" << endl; - return; - } - - PilotRecord *r = recordFromIncidence( de, e ); - - // TODO: Check for conflict! - if ( r ) - { - recordid_t id=fDatabase->writeRecord(r); - r->setID(id); -// r->setAttrib(r->getAttrib() & ~dlpRecAttrDeleted); - fLocalDatabase->writeRecord( r ); -// fDatabase->writeRecord(r); - e->setPilotId( id ); - - // NOTE: This MUST be done last, since every other set* call - // calls updated(), which will trigger an - // setSyncStatus(SYNCMOD)!!! - e->setSyncStatus(KCal::Incidence::SYNCNONE); - KPILOT_DELETE( r ); - } -} - -const TQString VCalConduitBase::dbname() -{ - return TQString::null; -} - -PilotRecord *VCalConduitBase::readRecordByIndex( int index ) -{ - FUNCTIONSETUP; - return fDatabase->readRecordByIndex( index ); -} - -KCal::Incidence *VCalConduitBase::incidenceFromRecord( PilotRecord *r ) -{ - FUNCTIONSETUP; - PilotRecordBase *pac = newPilotEntry( r ); - KCal::Incidence *i = newIncidence(); - incidenceFromRecord( i, pac ); - - KPILOT_DELETE( pac ); - return i; -} - -void VCalConduitBase::setState( ConduitState *s ) -{ - KPILOT_DELETE( fState ); - fState = s; -} - -/* virtual */ void VCalConduitBase::postSync( ) -{ - FUNCTIONSETUP; - if (fCtrPC && fP) - fCtrPC->setEndCount(fP->count()); -} - -/* virtual */ void VCalConduitBase::preSync( ) -{ - FUNCTIONSETUP; - if (fCtrPC && fP) - fCtrPC->setStartCount(fP->count()); -} |