diff options
Diffstat (limited to 'kpilot/lib/recordConduit.cc')
-rw-r--r-- | kpilot/lib/recordConduit.cc | 1145 |
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" - |