summaryrefslogtreecommitdiffstats
path: root/kpilot/lib/recordConduit.cc
diff options
context:
space:
mode:
Diffstat (limited to 'kpilot/lib/recordConduit.cc')
-rw-r--r--kpilot/lib/recordConduit.cc1145
1 files changed, 0 insertions, 1145 deletions
diff --git a/kpilot/lib/recordConduit.cc b/kpilot/lib/recordConduit.cc
deleted file mode 100644
index f7692de47..000000000
--- a/kpilot/lib/recordConduit.cc
+++ /dev/null
@@ -1,1145 +0,0 @@
-/* KPilot
-**
-** Copyright (C) 2004 by Reinhold Kainhofer
-** Based on the addressbook conduit:
-** Copyright (C) 2000,2001 by Dan Pilone
-** Copyright (C) 2000 Gregory Stern
-** Copyright (C) 2002-2003 by Reinhold Kainhofer
-**
-** This conduit is the base class for all record-based conduits.
-** all the sync logic is included in this class, and all child classes
-** just have to implement some specific copying and conflict resolution
-** methods.
-*/
-
-/*
-** 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 "pilotAppCategory.h"
-#include "pilotSerialDatabase.h"
-#include "pilotLocalDatabase.h"
-#include "recordConduit.h"
-
-
-// Something to allow us to check what revision
-// the modules are that make up a binary distribution.
-//
-//
-extern "C"
-{
-long version_record_conduit = Pilot::PLUGIN_API;
-}
-
-
-/* virtual */ bool RecordConduitBase::exec()
-{
- FUNCTIONSETUP;
- fState = Initialize;
-
- setFirstSync(false);
-
- bool retrieved = false;
- if (!openDatabases( fDBName, &retrieved))
- {
- emit logError(i18n("Unable to open the %1 database on the handheld.").arg( fDBName ) );
- return false;
- }
- if (retrieved) setFirstSync(true);
-
- if (isFirstSync()) fIDList=fDatabase->idList();
- else fIDList=fDatabase->modifiedIDList();
- fIDListIterator = fIDList.begin();
-
- fTimer = new TQTimer(this);
- connect(fTimer,TQT_SIGNAL(timeout()),this,TQT_SLOT(process()));
- fTimer->start(0,false); // Fire as often as possible to prompt processing
- return true;
-}
-
-/* virtual */ void RecordConduitBase::process()
-{
- FUNCTIONSETUP;
- SyncProgress p = Error;
-
-#ifdef DEBUG
- DEBUGKPILOT << fname << ": From state " << name(fState) << endl;
-#endif
-
- switch(fState)
- {
- case Initialize :
- p = loadPC();
- break;
- case PalmToPC :
- p = palmRecToPC();
- break;
- case PCToPalm :
- p = pcRecToPalm();
- break;
- case Cleanup :
- p = cleanup();
- break;
- }
-
-#ifdef DEBUG
- DEBUGKPILOT << fname << ": Step returned " << name(p) << endl;
-#endif
-
- switch(p)
- {
- case Error :
- fTimer->stop();
- delayDone();
- return;
- case NotDone :
- // Return so we get called again.
- return;
- case Done :
- // Get on with it.
- break;
- }
-
-#ifdef DEBUG
- DEBUGKPILOT << fname << ": Step is done, moving to next state." << endl;
-#endif
-
- // Here the previous call was done.
- switch(fState)
- {
- case Initialize :
- switch (syncMode().mode())
- {
- case SyncMode::eRestore :
- case SyncMode::eCopyPCToHH : /* These two don't copy Palm records to the PC */
- fState = PCToPalm;
- break;
- default :
- fState = PalmToPC;
- }
- break;
- case PalmToPC :
- switch (syncMode().mode())
- {
- case SyncMode::eBackup :
- case SyncMode::eCopyHHToPC : /* These modes don't copy PC records back */
- fState = Cleanup;
- break;
- default :
- fState = PCToPalm;
- }
- break;
- case PCToPalm :
- fState = Cleanup;
- break;
- case Cleanup :
- fTimer->stop();
- delayDone();
- // No change in state, timer stopped and we're done.
- break;
- }
-
-#ifdef DEBUG
- DEBUGKPILOT << fname << ": Next state is " << name(fState) << endl;
-#endif
-
-}
-
-
-TQString RecordConduitBase::name(RecordConduitBase::SyncProgress s)
-{
- switch(s)
- {
- case RecordConduitBase::NotDone:
- return CSL1("NotDone");
- case RecordConduitBase::Done:
- return CSL1("Done");
- case RecordConduitBase::Error:
- return CSL1("Error");
- }
-}
-
-
-TQString RecordConduitBase::name(RecordConduitBase::States s)
-{
- switch(s)
- {
- case RecordConduitBase::Initialize:
- return CSL1("Initialize");
- case RecordConduitBase::PalmToPC:
- return CSL1("Handheld-to-PC");
- case RecordConduitBase::PCToPalm:
- return CSL1("PC-to-Handheld");
- case RecordConduitBase::Cleanup:
- return CSL1("Cleanup");
- }
-}
-
-
-#if 0
-/** make that entry on the pc archived (i.e. deleted on the handheld,
- * while present on the pc, but not synced to the handheld */
-bool RecordConduit::PCData::makeArchived( RecordConduit::PCEntry *pcEntry )
-{
- if ( pcEntry ) {
- pcEntry->makeArchived();
- setChanged( true );
- return true;
- } else return false;
-}
-
-
-/* Builds the map which links record ids to uid's of PCEntry. This is the slow implementation,
- * that should always work. subclasses should reimplement it to speed things up.
-*/
-bool RecordConduit::PCData::mapContactsToPilot( TQMap<recordid_t,TQString> &idContactMap )
-{
- FUNCTIONSETUP;
-
- idContactMap.clear();
-
- Iterator it = begin();
- PCEntry *ent;
- while ( !atEnd( it ) ) {
- ent = *it;
- recordid_t id( ent->recid() );
- if ( id != 0 ) {
- idContactMap.insert( id, ent->uid() );
- }
- ++it;
- }
-#ifdef DEBUG
- DEBUGKPILOT << fname << ": Loaded " << idContactMap.size() <<
- " Entries on the pc and mapped them to records on the handheld. " << endl;
-#endif
- return true;
-}
-
-
-
-/*********************************************************************
- C O N S T R U C T O R
- *********************************************************************/
-
-
-
-bool RecordConduit::mArchiveDeleted = false;
-
-RecordConduit::RecordConduit(TQString name, KPilotDeviceLink * o, const char *n, const TQStringList & a):
- ConduitAction(o, n, a),
- mPCData(0), mPalmIndex(0),
- mEntryMap(), mSyncedIds(), mAllIds()
-{
- FUNCTIONSETUP;
- fConduitName = name;
-}
-
-
-
-RecordConduit::~RecordConduit()
-{
- if ( mPCData ) KPILOT_DELETE(mPCData);
-}
-
-
-
-
-
-
-/*********************************************************************
- S Y N C S T R U C T U R E
- *********************************************************************/
-
-
-
-/* virtual */ bool RecordConduit::exec()
-{
- FUNCTIONSETUP;
-
- if ( !_prepare() ) return false;
-
- fFirstSync = false;
- // Database names probably in latin1.
- if( !openDatabases( dbName(), &fFirstSync ) )
- {
- emit logError(i18n("Unable to open the %1 database on the handheld.").arg( dbName() ) );
- return false;
- }
- _getAppInfo();
- if( !mPCData->loadData() )
- {
- emit logError( i18n("Unable to open %1.").arg( mPCData->description() ) );
- return false;
- }
- // get the addresseMap which maps Pilot unique record(address) id's to
- // a Abbrowser Addressee; allows for easy lookup and comparisons
- if ( mPCData->isEmpty() )
- fFirstSync = true;
- else
- mPCData->mapContactsToPilot( mEntryMap );
- fFirstSync = fFirstSync || ( mPCData->isEmpty() );
-
- // perform syncing from palm to abbrowser
- // iterate through all records in palm pilot
- mPalmIndex = 0;
-
-#ifdef DEBUG
- DEBUGKPILOT << fname << ": fullsync=" << isFullSync() << ", firstSync=" << isFirstSync() << endl;
- DEBUGKPILOT << fname << ": "
- << "syncDirection=" << getSyncDirection() << ", "
-// << "archive = " << AbbrowserSettings::archiveDeleted()
- << endl;
- DEBUGKPILOT << fname << ": conflictRes="<< getConflictResolution() << endl;
-// DEBUGKPILOT << fname << ": PilotStreetHome=" << AbbrowserSettings::pilotStreet() << ", PilotFaxHOme" << AbbrowserSettings::pilotFax() << endl;
-#endif
-
- if ( !isFirstSync() )
- mAllIds=fDatabase->idList();
-
- /* Note:
- if eCopyPCToHH or eCopyHHToPC, first sync everything, then lookup
- those entries on the receiving side that are not yet syncced and delete
- them. Use slotDeleteUnsyncedPCRecords and slotDeleteUnsyncedHHRecords
- for this, and no longer purge the whole addressbook before the sync to
- prevent data loss in case of connection loss. */
-
- TQTimer::singleShot(0, this, TQT_SLOT(slotPalmRecToPC()));
-
- return true;
-}
-
-
-
-void RecordConduit::slotPalmRecToPC()
-{
- FUNCTIONSETUP;
- PilotRecord *palmRec = 0L, *backupRec = 0L;
-
- if ( getSyncDirection() == SyncAction::eCopyPCToHH )
- {
- mPCIter = mPCData->begin();
- TQTimer::singleShot(0, this, TQT_SLOT(slotPCRecToPalm()));
- return;
- }
-
- if ( isFullSync() )
- palmRec = fDatabase->readRecordByIndex( mPalmIndex++ );
- else
- palmRec = dynamic_cast <PilotSerialDatabase * >(fDatabase)->readNextModifiedRec();
-
- if ( !palmRec )
- {
- mPCIter = mPCData->begin();
- TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) );
- return;
- }
-
- // already synced, so skip:
- if ( mSyncedIds.contains( palmRec->id() ) )
- {
- KPILOT_DELETE( palmRec );
- TQTimer::singleShot( 0, this, TQT_SLOT( slotPalmRecToPC() ) );
- return;
- }
-
- backupRec = fLocalDatabase->readRecordById( palmRec->id() );
- PilotRecord *compareRec = backupRec ? backupRec : palmRec;
- PilotAppCategory *compareEntry = createPalmEntry( compareRec );
- PCEntry *pcEntry = findMatch( compareEntry );
- KPILOT_DELETE( compareEntry );
-
- PilotAppCategory *backupEntry=0L;
- if ( backupRec )
- backupEntry = createPalmEntry( backupRec );
- PilotAppCategory *palmEntry=0L;
- if ( palmRec )
- palmEntry = createPalmEntry( palmRec );
-
- syncEntry( pcEntry, backupEntry, palmEntry );
-
- mSyncedIds.append( palmRec->id() );
-
- KPILOT_DELETE( pcEntry );
- KPILOT_DELETE( palmEntry );
- KPILOT_DELETE( backupEntry );
- KPILOT_DELETE( palmRec );
- KPILOT_DELETE( backupRec );
-
- TQTimer::singleShot(0, this, TQT_SLOT(slotPalmRecToPC()));
-}
-
-
-
-void RecordConduit::slotPCRecToPalm()
-{
- FUNCTIONSETUP;
-
- if ( ( getSyncDirection()==SyncAction::eCopyHHToPC ) ||
- mPCData->atEnd( mPCIter ) )
- {
- mPalmIndex = 0;
- TQTimer::singleShot( 0, this, TQT_SLOT( slotDeletedRecord() ) );
- return;
- }
-
- PilotRecord *backupRec=0L;
- PCEntry *pcEntry = *mPCIter;
- ++mPCIter;
-
- // If marked as archived, don't sync!
- if ( isArchived( pcEntry ) )
- {
-#ifdef DEBUG
- DEBUGKPILOT << fname << ": address with id " << pcEntry->uid() <<
- " marked archived, so don't sync." << endl;
-#endif
- KPILOT_DELETE( pcEntry );
- TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) );
- return;
- }
-
- recordid_t recID( pcEntry->recid() );
- if ( recID == 0 )
- {
- // it's a new item(no record ID and not inserted by the Palm -> PC sync), so add it
- syncEntry( pcEntry, 0L, 0L );
- KPILOT_DELETE( pcEntry );
- TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) );
- return;
- }
-
- // look into the list of already synced record ids to see if the PCEntry hasn't already been synced
- if ( mSyncedIds.contains( recID ) )
- {
-#ifdef DEBUG
- DEBUGKPILOT << ": address with id " << recID << " already synced." << endl;
-#endif
- KPILOT_DELETE( pcEntry );
- TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) );
- return;
- }
-
-
- backupRec = fLocalDatabase->readRecordById( recID );
- // only update if no backup record or the backup record is not equal to the PCEntry
-
- PilotAppCategory*backupEntry=0L;
- if ( backupRec )
- backupEntry = createPalmEntry( backupRec );
- if( !backupRec || isFirstSync() || !_equal( backupEntry, pcEntry ) )
- {
- PilotRecord *palmRec = fDatabase->readRecordById( recID );
- PilotAppCategory *palmEntry=0L;
- if (palmRec)
- palmEntry = createPalmEntry( palmRec );
- syncEntry( pcEntry, backupEntry, palmEntry );
- // update the id just in case it changed
- if ( palmRec )
- recID = palmRec->id();
- KPILOT_DELETE( palmRec );
- KPILOT_DELETE( palmEntry );
- }
-
- KPILOT_DELETE( pcEntry );
- KPILOT_DELETE( backupEntry );
- KPILOT_DELETE( backupRec );
- mSyncedIds.append( recID );
-
- // done with the sync process, go on with the next one:
- TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) );
-}
-
-
-
-void RecordConduit::slotDeletedRecord()
-{
- FUNCTIONSETUP;
-
- PilotRecord *backupRec = fLocalDatabase->readRecordByIndex( mPalmIndex++ );
- if( !backupRec || isFirstSync() )
- {
- KPILOT_DELETE(backupRec);
- TQTimer::singleShot( 0, this, TQT_SLOT( slotDeleteUnsyncedPCRecords() ) );
- return;
- }
-
- // already synced, so skip this record:
- if ( mSyncedIds.contains( backupRec->id() ) )
- {
- KPILOT_DELETE( backupRec );
- TQTimer::singleShot( 0, this, TQT_SLOT( slotDeletedRecord() ) );
- return;
- }
-
- TQString uid = mEntryMap[ backupRec->id() ];
- PCEntry *pcEntry = mPCData->findByUid( uid );
- PilotRecord *palmRec = fDatabase->readRecordById( backupRec->id() );
- PilotAppCategory *backupEntry = 0L;
- if (backupRec)
- backupEntry = createPalmEntry( backupRec );
- PilotAppCategory*palmEntry=0L;
- if (palmRec)
- palmEntry = createPalmEntry( palmRec );
-
- mSyncedIds.append( backupRec->id() );
- syncEntry( pcEntry, backupEntry, palmEntry );
-
- KPILOT_DELETE( pcEntry );
- KPILOT_DELETE( palmEntry );
- KPILOT_DELETE( backupEntry );
- KPILOT_DELETE( palmRec );
- KPILOT_DELETE( backupRec );
- TQTimer::singleShot( 0, this, TQT_SLOT( slotDeletedRecord() ) );
-}
-
-
-
-void RecordConduit::slotDeleteUnsyncedPCRecords()
-{
- FUNCTIONSETUP;
- if ( getSyncDirection() == SyncAction::eCopyHHToPC )
- {
- TQStringList uids;
- RecordIDList::iterator it;
- TQString uid;
- for ( it = mSyncedIds.begin(); it != mSyncedIds.end(); ++it)
- {
- uid = mEntryMap[ *it ];
- if ( !uid.isEmpty() ) uids.append( uid );
- }
- // TODO: Does this speed up anything?
- // qHeapSort( uids );
- const TQStringList alluids( mPCData->uids() );
- TQStringList::ConstIterator uidit;
- for ( uidit = alluids.constBegin(); uidit != alluids.constEnd(); ++uidit )
- {
- if ( !uids.contains( *uidit ) )
- {
-#ifdef DEBUG
- DEBUGKPILOT << "Deleting PCEntry with uid " << (*uidit) << " from PC (is not on HH, and syncing with HH->PC direction)" << endl;
-#endif
- mPCData->removeEntry( *uidit );
- }
- }
- }
- TQTimer::singleShot(0, this, TQT_SLOT(slotDeleteUnsyncedHHRecords()));
-}
-
-
-
-void RecordConduit::slotDeleteUnsyncedHHRecords()
-{
- FUNCTIONSETUP;
- if ( getSyncDirection() == SyncAction::eCopyPCToHH )
- {
- RecordIDList ids = fDatabase->idList();
- RecordIDList::iterator it;
- for ( it = ids.begin(); it != ids.end(); ++it )
- {
- if ( !mSyncedIds.contains(*it) )
- {
-#ifdef DEBUG
- DEBUGKPILOT << "Deleting record with ID " << *it << " from handheld (is not on PC, and syncing with PC->HH direction)" << endl;
-#endif
- fDatabase->deleteRecord(*it);
- fLocalDatabase->deleteRecord(*it);
- }
- }
- }
- TQTimer::singleShot( 0, this, TQT_SLOT( slotCleanup() ) );
-}
-
-
-void RecordConduit::slotCleanup()
-{
- FUNCTIONSETUP;
-
- // Set the appInfoBlock, just in case the category labels changed
- _setAppInfo();
- doPostSync();
- if(fDatabase)
- {
- fDatabase->resetSyncFlags();
- fDatabase->cleanup();
- }
- if(fLocalDatabase)
- {
- fLocalDatabase->resetSyncFlags();
- fLocalDatabase->cleanup();
- }
- KPILOT_DELETE( fDatabase );
- KPILOT_DELETE( fLocalDatabase );
- // TODO: do something if saving fails!
- mPCData->saveData();
- mPCData->cleanup();
- emit syncDone(this);
-}
-
-
-/** Return the list of category names on the handheld
- */
-const TQStringList RecordConduit::categories() const
-{
- TQStringList cats;
- for ( unsigned int j = 0; j < Pilot::CATEGORY_COUNT; j++ ) {
- TQString catName( category( j ) );
- if ( !catName.isEmpty() ) cats << catName;
- }
- return cats;
-}
-int RecordConduit::findFlags() const
-{
- return eqFlagsAlmostAll;
-}
-
-
-bool RecordConduit::isDeleted( const PilotAppCategory *palmEntry )
-{
- if ( !palmEntry )
- return true;
- if ( palmEntry->isDeleted() && !palmEntry->isArchived() )
- return true;
- if ( palmEntry->isArchived() )
- return !archiveDeleted();
- return false;
-}
-bool RecordConduit::isArchived( const PilotAppCategory *palmEntry )
-{
- if ( palmEntry && palmEntry->isArchived() )
- return archiveDeleted();
- else
- return false;
-}
-
-
-
-
-/*********************************************************************
- L O A D I N G T H E D A T A
- *********************************************************************/
-
-
-
-bool RecordConduit::_prepare()
-{
- FUNCTIONSETUP;
-
- readConfig();
- mSyncedIds.clear();
- mPCData = initializePCData();
-
- return mPCData && doPrepare();
-}
-
-
-void RecordConduit::_getAppInfo()
-{
- FUNCTIONSETUP;
- // get the address application header information
- unsigned char *buffer = new unsigned char[Pilot::MAX_APPINFO_SIZE];
- int appLen=fDatabase->readAppBlock(buffer, Pilot::MAX_APPINFO_SIZE);
-
- doUnpackAppInfo( buffer, appLen );
- delete[] buffer;
- buffer = 0;
-}
-
-void RecordConduit::_setAppInfo()
-{
- FUNCTIONSETUP;
- // get the address application header information
- int appLen = 0;
- unsigned char *buffer = doPackAppInfo( &appLen );
- if ( buffer )
- { if (fDatabase)
- fDatabase->writeAppBlock( buffer, appLen );
- if (fLocalDatabase)
- fLocalDatabase->writeAppBlock( buffer, appLen );
- delete[] buffer;
- }
-}
-
-
-int RecordConduit::compareStr( const TQString & str1, const TQString & str2 )
-{
-// FUNCTIONSETUP;
- if ( str1.isEmpty() && str2.isEmpty() )
- return 0;
- else
- return str1.compare( str2 );
-}
-
-
-/**
- * _getCat returns the id of the category from the given categories list.
- * If the address has no categories on the PC, TQString::null is returned.
- * If the current category exists in the list of cats, it is returned
- * Otherwise the first cat in the list that exists on the HH is returned
- * If none of the categories exists on the palm, TQString::null is returned
- */
-TQString RecordConduit::getCatForHH( const TQStringList cats, const TQString curr ) const
-{
- FUNCTIONSETUP;
- if ( cats.size() < 1 )
- return TQString::null;
- if ( cats.contains( curr ) )
- return curr;
- for ( TQStringList::ConstIterator it = cats.begin(); it != cats.end(); ++it)
- {
- for ( unsigned int j = 0; j < Pilot::CATEGORY_COUNT; j++ )
- {
- TQString catnm( category( j ) );
- if ( !(*it).isEmpty() && ( (*it)==catnm ) )
- {
- return catnm;
- }
- }
- }
- // If we have a free label, return the first possible cat
- TQString lastCat( category( Pilot::CATEGORY_COUNT-1 ) );
- return ( lastCat.isEmpty() ) ? ( cats.first() ) : ( TQString::null );
-}
-
-void RecordConduit::setCategory(PCEntry * pcEntry, TQString cat)
-{
- if ( !cat.isEmpty() && cat!=category( 0 ) )
- pcEntry->insertCategory(cat);
-}
-
-
-
-
-
-
-/*********************************************************************
- G E N E R A L S Y N C F U N C T I O N
- These functions modify the Handheld and the addressbook
- *********************************************************************/
-
-
-
-bool RecordConduit::syncEntry( PCEntry *pcEntry, PilotAppCategory*backupEntry,
- PilotAppCategory*palmEntry)
-{
- FUNCTIONSETUP;
-
- if ( getSyncDirection() == SyncAction::eCopyPCToHH )
- {
- if ( pcEntry->isEmpty() )
- {
- return pcDeleteEntry( pcEntry, backupEntry, palmEntry );
- }
- else
- {
- return pcCopyToPalm( pcEntry, backupEntry, palmEntry );
- }
- }
-
- if ( getSyncDirection() == SyncAction::eCopyHHToPC )
- {
- if (!palmEntry)
- return pcDeleteEntry(pcEntry, backupEntry, palmEntry);
- else
- return palmCopyToPC(pcEntry, backupEntry, palmEntry);
- }
-
- if ( !backupEntry || isFirstSync() )
- {
- /*
- Resolution matrix (0..does not exist, E..exists, D..deleted flag set, A..archived):
- HH PC | Resolution
- ------------------------------------------------------------
- 0 A | -
- 0 E | PC -> HH, reset ID if not set correctly
- D 0 | delete (error, should never occur!!!)
- D E | CR (ERROR)
- E/A 0 | HH -> PC
- E/A E/A| merge/CR
- */
- if ( !palmEntry && isArchived( pcEntry ) )
- {
- return true;
- }
- else if ( !palmEntry && !pcEntry->isEmpty() )
- {
- // PC->HH
- bool res = pcCopyToPalm( pcEntry, 0L, 0L );
- return res;
- }
- else if ( !palmEntry && pcEntry->isEmpty() )
- {
- // everything's empty -> ERROR
- return false;
- }
- else if ( ( isDeleted( palmEntry ) || isArchived( palmEntry ) ) && pcEntry->isEmpty())
- {
- if ( isArchived( palmEntry ) )
- return palmCopyToPC( pcEntry, 0L, palmEntry );
- else
- // this happens if you add a record on the handheld and delete it again before you do the next sync
- return pcDeleteEntry( pcEntry, 0L, palmEntry );
- }
- else if ( ( isDeleted(palmEntry) || isArchived( palmEntry ) ) && !pcEntry->isEmpty() )
- {
- // CR (ERROR)
- return smartMergeEntry( pcEntry, 0L, palmEntry );
- }
- else if ( pcEntry->isEmpty() )
- {
- // HH->PC
- return palmCopyToPC( pcEntry, 0L, palmEntry );
- }
- else
- {
- // Conflict Resolution
- return smartMergeEntry( pcEntry, 0L, palmEntry );
- }
- } // !backupEntry
- else
- {
- /*
- Resolution matrix:
- 1) if HH.(empty| (deleted &! archived) ) -> { if (PC==B) -> delete, else -> CR }
- if HH.archived -> {if (PC==B) -> copyToPC, else -> CR }
- if PC.empty -> { if (HH==B) -> delete, else -> CR }
- if PC.archived -> {if (HH==B) -> delete on HH, else CR }
- 2) if PC==HH -> { update B, update ID of PC if needed }
- 3) if PC==B -> { HH!=PC, thus HH modified, so copy HH->PC }
- if HH==B -> { PC!=HH, thus PC modified, so copy PC->HH }
- 4) else: all three PCEntrys are different -> CR
- */
-
- if ( !palmEntry || isDeleted(palmEntry) )
- {
- if ( _equal( backupEntry, pcEntry ) || pcEntry->isEmpty() )
- {
- return pcDeleteEntry( pcEntry, backupEntry, 0L );
- }
- else
- {
- return smartMergeEntry( pcEntry, backupEntry, 0L );
- }
- }
- else if ( pcEntry->isEmpty() )
- {
- if (*palmEntry == *backupEntry)
- {
- return pcDeleteEntry( pcEntry, backupEntry, palmEntry );
- }
- else
- {
- return smartMergeEntry( pcEntry, backupEntry, palmEntry );
- }
- }
- else if ( _equal( palmEntry, pcEntry ) )
- {
- // update Backup, update ID of PC if neededd
- return backupSaveEntry( palmEntry );
- }
- else if ( _equal( backupEntry, pcEntry ) )
- {
-#ifdef DEBUG
- DEBUGKPILOT << "Flags: " << palmEntry->getAttrib() << ", isDeleted=" <<
- isDeleted( palmEntry ) << ", isArchived=" << isArchived( palmEntry )
- << endl;
-#endif
- if ( isDeleted( palmEntry ) )
- {
- return pcDeleteEntry( pcEntry, backupEntry, palmEntry );
- }
- else
- {
- return palmCopyToPC( pcEntry, backupEntry, palmEntry );
- }
- }
- else if ( *palmEntry == *backupEntry )
- {
- return pcCopyToPalm( pcEntry, backupEntry, palmEntry );
- }
- else
- {
- // CR, since all are different
- return smartMergeEntry( pcEntry, backupEntry, palmEntry );
- }
- } // backupEntry
- return false;
-}
-
-bool RecordConduit::pcCopyToPalm( PCEntry *pcEntry, PilotAppCategory *backupEntry,
- PilotAppCategory*palmEntry )
-{
- FUNCTIONSETUP;
-
- if ( pcEntry->isEmpty() ) return false;
- PilotAppCategory *hhEntry = palmEntry;
- bool hhEntryCreated = false;
- if ( !hhEntry )
- {
- hhEntry = createPalmEntry( 0 );
- hhEntryCreated=true;
- }
- _copy( hhEntry, pcEntry );
-#ifdef DEBUG
- DEBUGKPILOT << "palmEntry->id=" << hhEntry->id() << ", pcEntry.ID=" <<
- pcEntry->uid() << endl;
-#endif
-
- if( palmSaveEntry( hhEntry, pcEntry ) )
- {
-#ifdef DEBUG
- DEBUGKPILOT << "Entry palmEntry->id=" <<
- hhEntry->id() << "saved to palm, now updating pcEntry->uid()=" << pcEntry->uid() << endl;
-#endif
- pcSaveEntry( pcEntry, backupEntry, hhEntry );
- }
- if ( hhEntryCreated ) KPILOT_DELETE( hhEntry );
- return true;
-}
-
-
-
-
-bool RecordConduit::palmCopyToPC( PCEntry *pcEntry, PilotAppCategory *backupEntry,
- PilotAppCategory *palmEntry )
-{
- FUNCTIONSETUP;
- if ( !palmEntry )
- {
- return false;
- }
- _copy( pcEntry, palmEntry );
- pcSaveEntry( pcEntry, backupEntry, palmEntry );
- backupSaveEntry( palmEntry );
- return true;
-}
-
-
-
-/*********************************************************************
- l o w - l e v e l f u n c t i o n s f o r
- adding / removing palm/pc records
- *********************************************************************/
-
-
-
-bool RecordConduit::palmSaveEntry( PilotAppCategory *palmEntry, PCEntry *pcEntry )
-{
- FUNCTIONSETUP;
-
-#ifdef DEBUG
- DEBUGKPILOT << "Saving to pilot " << palmEntry->id() << endl;
-#endif
-
- PilotRecord *pilotRec = palmEntry->pack();
- recordid_t pilotId = fDatabase->writeRecord(pilotRec);
-#ifdef DEBUG
- DEBUGKPILOT << "PilotRec nach writeRecord (" << pilotId <<
- ": ID=" << pilotRec->id() << endl;
-#endif
- fLocalDatabase->writeRecord( pilotRec );
- KPILOT_DELETE( pilotRec );
-
- // pilotId == 0 if using local db, so don't overwrite the valid id
- if ( pilotId != 0 )
- {
- palmEntry->setID( pilotId );
- if ( !mSyncedIds.contains( pilotId ) )
- {
- mSyncedIds.append( pilotId );
- }
- }
-
- recordid_t hhId( pcEntry->recid() );
- if ( hhId != pilotId )
- {
- pcEntry->setRecid( pilotId );
- return true;
- }
-
- return false;
-}
-
-
-
-bool RecordConduit::backupSaveEntry( PilotAppCategory *backup )
-{
- FUNCTIONSETUP;
- if ( !backup ) return false;
-
-
-#ifdef DEBUG
-// showPilotAppCategory( backup );
-#endif
- PilotRecord *pilotRec = backup->pack();
- fLocalDatabase->writeRecord( pilotRec );
- KPILOT_DELETE( pilotRec );
- return true;
-}
-
-
-
-bool RecordConduit::pcSaveEntry( PCEntry *pcEntry, PilotAppCategory *,
- PilotAppCategory * )
-{
- FUNCTIONSETUP;
-
-#ifdef DEBUG
- DEBUGKPILOT << "Before _savepcEntry, pcEntry->uid()=" <<
- pcEntry->uid() << endl;
-#endif
- if ( pcEntry->recid() != 0 )
- {
- mEntryMap.insert( pcEntry->recid(), pcEntry->uid() );
- }
-
- mPCData->updateEntry( pcEntry );
- return true;
-}
-
-
-
-bool RecordConduit::pcDeleteEntry( PCEntry *pcEntry, PilotAppCategory *backupEntry,
- PilotAppCategory *palmEntry )
-{
- FUNCTIONSETUP;
-
- if ( palmEntry )
- {
- if ( !mSyncedIds.contains( palmEntry->id() ) )
- {
- mSyncedIds.append(palmEntry->id());
- }
- palmEntry->makeDeleted();
- PilotRecord *pilotRec = palmEntry->pack();
- pilotRec->setDeleted();
- mPalmIndex--;
- fDatabase->writeRecord( pilotRec );
- fLocalDatabase->writeRecord( pilotRec );
- mSyncedIds.append( pilotRec->id() );
- KPILOT_DELETE( pilotRec );
- }
- else if ( backupEntry )
- {
- if ( !mSyncedIds.contains( backupEntry->id() ) )
- {
- mSyncedIds.append( backupEntry->id() );
- }
- backupEntry->makeDeleted();
- PilotRecord *pilotRec = backupEntry->pack();
- pilotRec->setDeleted();
- mPalmIndex--;
- fLocalDatabase->writeRecord( pilotRec );
- mSyncedIds.append( pilotRec->id() );
- KPILOT_DELETE( pilotRec );
- }
- if ( !pcEntry->isEmpty() )
- {
-#ifdef DEBUG
- DEBUGKPILOT << fname << " removing " << pcEntry->uid() << endl;
-#endif
- mPCData->removeEntry( pcEntry );
- }
- return true;
-}
-
-
-
-/*********************************************************************
- C O P Y R E C O R D S
- *********************************************************************/
-
-
-
-
-
-/*********************************************************************
- C O N F L I C T R E S O L U T I O N a n d M E R G I N G
- *********************************************************************/
-
-
-
-
-// TODO: right now entries are equal if both first/last name and organization are
-// equal. This rules out two entries for the same person(e.g. real home and weekend home)
-// or two persons with the same name where you don't know the organization.!!!
-RecordConduit::PCEntry *RecordConduit::findMatch( PilotAppCategory *palmEntry ) const
-{
- FUNCTIONSETUP;
- if ( !palmEntry )
- return 0;
-
- // TODO: also search with the pilotID
- // first, use the pilotID to UID map to find the appropriate record
- if( !isFirstSync() && ( palmEntry->id() > 0) )
- {
- TQString id( mEntryMap[palmEntry->id()] );
-#ifdef DEBUG
- DEBUGKPILOT << fname << ": PilotRecord has id " << palmEntry->id() << ", mapped to " << id << endl;
-#endif
- if( !id.isEmpty() )
- {
- PCEntry *res = mPCData->findByUid( id );
- if ( !res && !res->isEmpty() ) return res;
- KPILOT_DELETE( res );
-#ifdef DEBUG
- DEBUGKPILOT << fname << ": PilotRecord has id " << palmEntry->id() <<
- ", but could not be found on the PC side" << endl;
-#endif
- }
- }
-
- for ( PCData::Iterator iter = mPCData->begin(); !mPCData->atEnd( iter ); ++iter )
- {
- PCEntry *abEntry = *iter;
- recordid_t rid( abEntry->recid() );
- if ( rid>0 )
- {
- if ( rid == palmEntry->id() )
- return abEntry;// yes, we found it
- // skip this PCEntry, as it has a different corresponding address on the handheld
- //if ( mAllIds.contains( rid ) ) continue;
- }
-
- if ( _equal( palmEntry, abEntry, eqFlagsAlmostAll ) )
- {
- return abEntry;
- }
- KPILOT_DELETE( abEntry );
- }
-#ifdef DEBUG
- DEBUGKPILOT << fname << ": Could not find any entry matching Palm record with id " << TQString::number( palmEntry->id() ) << endl;
-#endif
- return 0;
-}
-
-#endif
-
-
-
-
-#include "recordConduit.moc"
-