00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "options.h"
00037 #include "doc-conduit.moc"
00038
00039 #include <qtimer.h>
00040 #include <qdir.h>
00041
00042 #include <kconfig.h>
00043 #include <kcodecs.h>
00044
00045 #include <pilotLocalDatabase.h>
00046 #include <pilotSerialDatabase.h>
00047
00048 #include "doc-conflictdialog.h"
00049 #include "DOC-converter.h"
00050 #include "pilotDOCHead.h"
00051 #include "docconduitSettings.h"
00052
00053
00054 QString dirToString(eSyncDirectionEnum dir) {
00055 switch(dir) {
00056
00057 case eSyncPDAToPC: return CSL1("eSyncPDAToPC");
00058 case eSyncPCToPDA: return CSL1("eSyncPCToPDA");
00059 case eSyncNone: return CSL1("eSyncNone");
00060 case eSyncConflict: return CSL1("eSyncConflict");
00061 case eSyncDelete: return CSL1("eSyncDelete");
00062 default: return CSL1("ERROR");
00063 }
00064 }
00065
00066
00067
00068
00069
00070
00071
00072 DOCConduit::DOCConduit(KPilotLink * o,
00073 const QVariantList & a):ConduitAction(o, a)
00074 {
00075 FUNCTIONSETUP;
00076 fConduitName=i18n("DOC");
00077 }
00078
00079
00080
00081 DOCConduit::~DOCConduit()
00082 {
00083 FUNCTIONSETUP;
00084 }
00085
00086
00087 bool DOCConduit::isCorrectDBTypeCreator(DBInfo dbinfo) {
00088 return dbinfo.type == dbtype() && dbinfo.creator == dbcreator();
00089 }
00090
00091 static const char *dbDOCtype = "TEXt";
00092 static const char *dbDOCcreator = "REAd";
00093
00094 const unsigned long DOCConduit::dbtype() {
00095 return get_long(dbDOCtype);
00096 }
00097 const unsigned long DOCConduit::dbcreator() {
00098 return get_long(dbDOCcreator);
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 void DOCConduit::readConfig()
00110 {
00111 FUNCTIONSETUP;
00112 DOCConduitSettings::self()->readConfig();
00113
00114 eConflictResolution = (enum eSyncDirectionEnum) (DOCConduitSettings::conflictResolution() );
00115 fTXTBookmarks = DOCConverter::eBmkNone;
00116 if ( DOCConduitSettings::convertBookmarks() )
00117 {
00118 if ( DOCConduitSettings::bmkFileBookmarks() )
00119 fTXTBookmarks |= DOCConverter::eBmkFile;
00120 if ( DOCConduitSettings::inlineBookmarks() )
00121 fTXTBookmarks |= DOCConverter::eBmkInline;
00122 if ( DOCConduitSettings::endtagBookmarks() )
00123 fTXTBookmarks |= DOCConverter::eBmkEndtags;
00124 }
00125
00126 eSyncDirection = (enum eSyncDirectionEnum)(DOCConduitSettings::syncDirection() );
00127 }
00128
00129
00130
00131 bool DOCConduit::pcTextChanged(QString txtfn)
00132 {
00133 FUNCTIONSETUP;
00134
00135
00136
00137 QString oldDigest=DOCConduitSettings::self()->config()->readEntry(txtfn,QString());
00138 if (oldDigest.length()<=0)
00139 {
00140 return true;
00141 }
00142 #ifdef DEBUG
00143 DEBUGKPILOT<<"Old digest is"<<oldDigest;
00144 #endif
00145
00146 KMD5 docmd5;
00147 QFile txtfile(txtfn);
00148 if (txtfile.open(QIODevice::ReadOnly)){
00149 docmd5.update(txtfile);
00150 QString thisDigest(docmd5.hexDigest() );
00151 #ifdef DEBUG
00152 DEBUGKPILOT<<"New digest is"<<thisDigest;
00153 #endif
00154 return (thisDigest.length()<=0) || (thisDigest!=oldDigest);
00155 } else {
00156
00157
00158 return true;
00159 }
00160 return false;
00161 }
00162
00163
00164
00165 bool DOCConduit::hhTextChanged(PilotDatabase*docdb)
00166 {
00167 FUNCTIONSETUP;
00168 if (!docdb) return false;
00169
00170 PilotRecord *firstRec = docdb->readRecordByIndex(0);
00171 PilotDOCHead docHeader(firstRec);
00172 KPILOT_DELETE(firstRec);
00173
00174 int storyRecs = docHeader.numRecords;
00175
00176
00177
00178 int modRecInd=-1;
00179 PilotRecord*modRec=docdb->readNextModifiedRec(&modRecInd);
00180 #ifdef DEBUG
00181 DEBUGKPILOT<<"Index of first changed record:"<<modRecInd;
00182 #endif
00183
00184 KPILOT_DELETE(modRec);
00185
00186
00187 if (modRecInd==0) {
00188 modRec=docdb->readNextModifiedRec(&modRecInd);
00189 #ifdef DEBUG
00190 DEBUGKPILOT<<"Reread Index of first changed records:"<<modRecInd;
00191 #endif
00192 KPILOT_DELETE(modRec);
00193 }
00194
00195
00196
00197 if (modRecInd >= 0) {
00198 if ((!DOCConduitSettings::ignoreBmkChanges()) || (modRecInd <= storyRecs))
00199 return true;
00200 } else {
00201 return false;
00202 }
00203 return false;
00204 }
00205
00206
00207
00208
00209
00210
00211
00212 QString DOCConduit::constructPDBFileName(QString name) {
00213 FUNCTIONSETUP;
00214 QString fn;
00215 QDir dr(DOCConduitSettings::pDBDirectory());
00216 QFileInfo pth(dr, name);
00217 if (!name.isEmpty()) fn=pth.absoluteFilePath()+CSL1(".pdb");
00218 return fn;
00219 }
00220 QString DOCConduit::constructTXTFileName(QString name) {
00221 FUNCTIONSETUP;
00222 QString fn;
00223 QDir dr( DOCConduitSettings::tXTDirectory() );
00224 QFileInfo pth(dr, name);
00225 if (!name.isEmpty()) fn=pth.absoluteFilePath()+CSL1(".txt");
00226 return fn;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 bool DOCConduit::exec()
00242 {
00243 FUNCTIONSETUP;
00244
00245 readConfig();
00246 dbnr=0;
00247
00248 emit logMessage(i18n("Searching for texts and databases to synchronize"));
00249
00250 QTimer::singleShot(0, this, SLOT(syncNextDB()));
00251 return true;
00252 }
00253
00254
00255
00256 bool DOCConduit::doSync(docSyncInfo &sinfo)
00257 {
00258 FUNCTIONSETUP;
00259 bool res=false;
00260
00261 if (sinfo.direction==eSyncDelete) {
00262 if (!sinfo.txtfilename.isEmpty()) {
00263 if (!QFile::remove(sinfo.txtfilename)) {
00264 WARNINGKPILOT <<"Unable to delete the text file" << sinfo.txtfilename <<" on the PC";
00265 }
00266 QString bmkfilename = sinfo.txtfilename;
00267 if (bmkfilename.endsWith(CSL1(".txt"))){
00268 bmkfilename.remove(bmkfilename.length()-4, 4);
00269 }
00270 bmkfilename+=CSL1(PDBBMK_SUFFIX);
00271 if (!QFile::remove(bmkfilename)) {
00272 #ifdef DEBUG
00273 DEBUGKPILOT<<"Could not remove bookmarks file"<<bmkfilename<<" for database"<<sinfo.handheldDB;
00274 #endif
00275 }
00276 }
00277 if (!sinfo.pdbfilename.isEmpty() && DOCConduitSettings::keepPDBsLocally() ) {
00278 PilotLocalDatabase*database=new PilotLocalDatabase(DOCConduitSettings::pDBDirectory(),
00279 QString::fromLatin1(sinfo.dbinfo.name), false);
00280 if (database) {
00281 if ( database->deleteDatabase() !=0 ) {
00282 WARNINGKPILOT <<"Unable to delete database" << sinfo.dbinfo.name <<" on the PC";
00283 }
00284 KPILOT_DELETE(database);
00285 }
00286 }
00287 if (!DOCConduitSettings::localSync()) {
00288 PilotDatabase *database=deviceLink()->database( sinfo.dbinfo.name );
00289 if ( database->deleteDatabase() !=0 ) {
00290 WARNINGKPILOT <<"Unable to delete database" << sinfo.dbinfo.name <<" from the handheld";
00291 }
00292 KPILOT_DELETE(database);
00293 }
00294 return true;
00295 }
00296
00297
00298
00299 PilotDatabase *database = preSyncAction(sinfo);
00300
00301 if (database && ( !database->isOpen() ) ) {
00302 #ifdef DEBUG
00303 DEBUGKPILOT<<"Database"<<sinfo.dbinfo.name<<" does not yet exist. Creating it:";
00304 #endif
00305 if (!database->createDatabase(dbcreator(), dbtype()) ) {
00306 #ifdef DEBUG
00307 DEBUGKPILOT<<"Failed";
00308 emit logMessage(i18n("Database created."));
00309 #endif
00310 }
00311 }
00312
00313 if (database && database->isOpen()) {
00314 DOCConverter docconverter;
00315 connect(&docconverter, SIGNAL(logError(const QString &)), SIGNAL(logError(const QString &)));
00316 connect(&docconverter, SIGNAL(logMessage(const QString &)), SIGNAL(logMessage(const QString &)));
00317
00318 docconverter.setTXTpath( DOCConduitSettings::tXTDirectory(), sinfo.txtfilename );
00319 docconverter.setPDB(database);
00320 docconverter.setCompress(DOCConduitSettings::compress());
00321
00322 switch (sinfo.direction) {
00323 case eSyncPDAToPC:
00324 docconverter.setBookmarkTypes(DOCConduitSettings::bookmarksToPC());
00325 res = docconverter.convertPDBtoTXT();
00326 break;
00327 case eSyncPCToPDA:
00328 docconverter.setBookmarkTypes(fTXTBookmarks);
00329 res = docconverter.convertTXTtoPDB();
00330 break;
00331 default:
00332 break;
00333 }
00334
00335
00336 if (res)
00337 {
00338 KMD5 docmd5;
00339 QFile txtfile(docconverter.txtFilename());
00340 if (txtfile.open(QIODevice::ReadOnly)) {
00341 docmd5.update(txtfile);
00342 QString thisDigest(docmd5.hexDigest() );
00343 DOCConduitSettings::self()->config()->writeEntry(docconverter.txtFilename(), thisDigest);
00344 DOCConduitSettings::self()->config()->sync();
00345 #ifdef DEBUG
00346 DEBUGKPILOT<<"MD5 Checksum of the text"<<sinfo.txtfilename<<" is"<<thisDigest;
00347 #endif
00348 } else {
00349 #ifdef DEBUG
00350 DEBUGKPILOT<<"could not open file"<<docconverter.txtFilename()<<" for reading!!!";
00351 #endif
00352 }
00353 }
00354
00355 if (!postSyncAction(database, sinfo, res))
00356 emit logError(i18n("Unable to install the locally created PalmDOC %1 to the handheld.",
00357 QString::fromLatin1(sinfo.dbinfo.name)));
00358 if (!res)
00359 emit logError(i18n("Conversion of PalmDOC \"%1\" failed.",
00360 QString::fromLatin1(sinfo.dbinfo.name)));
00361
00362
00363
00364 }
00365 else
00366 {
00367 emit logError(i18n("Unable to open or create the database %1.",
00368 QString::fromLatin1(sinfo.dbinfo.name)));
00369 }
00370 return res;
00371 }
00372
00373
00376 void DOCConduit::syncNextDB() {
00377 FUNCTIONSETUP;
00378 DBInfo dbinfo;
00379
00380 if (eSyncDirection==eSyncPCToPDA || fHandle->findDatabase(NULL, &dbinfo, dbnr, dbtype(), dbcreator() ) < 0)
00381 {
00382
00383 QTimer::singleShot(0, this, SLOT(syncNextTXT()));
00384 return;
00385 }
00386 dbnr=dbinfo.index+1;
00387 #ifdef DEBUG
00388 DEBUGKPILOT<<"Next Palm database to sync:"<<dbinfo.name<<", Index="<<dbinfo.index;
00389 #endif
00390
00391
00392 if (!isCorrectDBTypeCreator(dbinfo) ||
00393 fDBNames.contains(QString::fromLatin1(dbinfo.name)))
00394 {
00395 QTimer::singleShot(0, this, SLOT(syncNextDB()));
00396 return;
00397 }
00398
00399 QString txtfilename=constructTXTFileName(QString::fromLatin1(dbinfo.name));
00400 QString pdbfilename=constructPDBFileName(QString::fromLatin1(dbinfo.name));
00401
00402 docSyncInfo syncInfo(QString::fromLatin1(dbinfo.name),
00403 txtfilename, pdbfilename, eSyncNone);
00404 syncInfo.dbinfo=dbinfo;
00405 needsSync(syncInfo);
00406 fSyncInfoList.append(syncInfo);
00407 fDBNames.append(QString::fromLatin1(dbinfo.name));
00408
00409 QTimer::singleShot(0, this, SLOT(syncNextDB()));
00410 return;
00411 }
00412
00413
00414
00415 void DOCConduit::syncNextTXT()
00416 {
00417 FUNCTIONSETUP;
00418
00419 if (eSyncDirection==eSyncPDAToPC )
00420 {
00421
00422 docnames.clear();
00423 QTimer::singleShot(0, this, SLOT(checkPDBFiles()));
00424 return;
00425 }
00426
00427
00428 if (docnames.isEmpty()) {
00429 docnames=QDir( DOCConduitSettings::tXTDirectory(), CSL1("*.txt")).entryList() ;
00430 dociterator=docnames.begin();
00431 }
00432 if (dociterator==docnames.end()) {
00433
00434 docnames.clear();
00435 QTimer::singleShot(0, this, SLOT(checkPDBFiles()));
00436 return;
00437 }
00438
00439 QString fn=(*dociterator);
00440
00441 QDir dr( DOCConduitSettings::tXTDirectory() );
00442 QFileInfo fl(dr, fn );
00443 QString txtfilename=fl.absoluteFilePath();
00444 QString pdbfilename;
00445 ++dociterator;
00446
00447 DBInfo dbinfo;
00448
00449
00450 memset(&dbinfo.name[0], 0, 33);
00451 strncpy(&dbinfo.name[0], fl.baseName(true).latin1(), 30);
00452
00453 bool alreadySynced=fDBNames.contains(fl.baseName(true));
00454 if (!alreadySynced) {
00455 docSyncInfo syncInfo(QString::fromLatin1(dbinfo.name),
00456 txtfilename, pdbfilename, eSyncNone);
00457 syncInfo.dbinfo=dbinfo;
00458 needsSync(syncInfo);
00459 fSyncInfoList.append(syncInfo);
00460 fDBNames.append(QString::fromLatin1(dbinfo.name));
00461 } else {
00462 #ifdef DEBUG
00463 DEBUGKPILOT<<txtfilename<<" has already been synced, skipping it.";
00464 #endif
00465 }
00466
00467 QTimer::singleShot(0, this, SLOT(syncNextTXT()));
00468 return;
00469 }
00470
00471
00472
00475 void DOCConduit::checkPDBFiles() {
00476 FUNCTIONSETUP;
00477
00478 if ( DOCConduitSettings::localSync() || !DOCConduitSettings::keepPDBsLocally() || eSyncDirection==eSyncPCToPDA )
00479 {
00480
00481 QTimer::singleShot(0, this, SLOT(checkDeletedDocs()));
00482 return;
00483 }
00484
00485
00486
00487 if (docnames.isEmpty()) {
00488 docnames=QDir(DOCConduitSettings::pDBDirectory(), CSL1("*.pdb")).entryList() ;
00489 dociterator=docnames.begin();
00490 }
00491 if (dociterator==docnames.end()) {
00492
00493 docnames.clear();
00494 QTimer::singleShot(0, this, SLOT(checkDeletedDocs()));
00495 return;
00496 }
00497
00498 QString fn=(*dociterator);
00499
00500 QDir dr(DOCConduitSettings::pDBDirectory());
00501 QFileInfo fl(dr, fn );
00502 QString pdbfilename=fl.absoluteFilePath();
00503 ++dociterator;
00504
00505
00506
00507 QString dbname=fl.baseName(true).left(30);
00508 if (!fDBNames.contains(dbname) && !fDBListSynced.contains(dbname)) {
00509 if (fHandle->installFiles( QStringList(pdbfilename), false)) {
00510 DBInfo dbinfo;
00511
00512
00513 memset(&dbinfo.name[0], 0, 33);
00514 strncpy(&dbinfo.name[0], dbname.latin1(), 30);
00515
00516 docSyncInfo syncInfo(dbname, constructTXTFileName(dbname), pdbfilename, eSyncNone);
00517 syncInfo.dbinfo=dbinfo;
00518 needsSync(syncInfo);
00519 fSyncInfoList.append(syncInfo);
00520 fDBNames.append(dbname);
00521 } else {
00522 #ifdef DEBUG
00523 DEBUGKPILOT<<"Could not install database"<<dbname<<" ("<<pdbfilename<<") to the handheld";
00524 #endif
00525 }
00526 }
00527
00528 QTimer::singleShot(0, this, SLOT(checkPDBFiles()));
00529 }
00530
00531
00532
00533 void DOCConduit::checkDeletedDocs()
00534 {
00535 FUNCTIONSETUP;
00536
00537 for (QStringList::Iterator it=fDBListSynced.begin(); it!=fDBListSynced.end(); ++it ) {
00538 if (!fDBNames.contains(*it)) {
00539
00540 QString dbname(*it);
00541 QString txtfilename=constructTXTFileName(dbname);
00542 QString pdbfilename=constructPDBFileName(dbname);
00543 docSyncInfo syncInfo(dbname, txtfilename, pdbfilename, eSyncDelete);
00544
00545 DBInfo dbinfo;
00546 memset(&dbinfo.name[0], 0, 33);
00547 strncpy(&dbinfo.name[0], dbname.latin1(), 30);
00548 syncInfo.dbinfo=dbinfo;
00549
00550 fSyncInfoList.append(syncInfo);
00551 }
00552 }
00553 QTimer::singleShot(0, this, SLOT(resolve()));
00554 return;
00555 }
00556
00557
00558
00559 void DOCConduit::resolve() {
00560 FUNCTIONSETUP;
00561
00562 for (fSyncInfoListIterator=fSyncInfoList.begin(); fSyncInfoListIterator!=fSyncInfoList.end(); ++fSyncInfoListIterator) {
00563
00564
00565 if ((*fSyncInfoListIterator).direction==eSyncConflict){
00566 #ifdef DEBUG
00567 DEBUGKPILOT<<"We have a conflict for"<<(*fSyncInfoListIterator).handheldDB<<", default="<<eConflictResolution;
00568 #endif
00569 switch (eConflictResolution)
00570 {
00571 case eSyncPDAToPC:
00572 #ifdef DEBUG
00573 DEBUGKPILOT<<"PDA overrides for database"<<(*fSyncInfoListIterator).handheldDB;
00574 #endif
00575 (*fSyncInfoListIterator).direction = eSyncPDAToPC;
00576 break;
00577 case eSyncPCToPDA:
00578 #ifdef DEBUG
00579 DEBUGKPILOT<<"PC overrides for database"<<(*fSyncInfoListIterator).handheldDB;
00580 #endif
00581 (*fSyncInfoListIterator).direction = eSyncPCToPDA;
00582 break;
00583 case eSyncNone:
00584 #ifdef DEBUG
00585 DEBUGKPILOT<<"No sync for database"<<(*fSyncInfoListIterator).handheldDB;
00586 #endif
00587 (*fSyncInfoListIterator).direction = eSyncNone;
00588 break;
00589 case eSyncDelete:
00590 case eSyncConflict:
00591 default:
00592 #ifdef DEBUG
00593 DEBUGKPILOT<<"Conflict remains due to default resolution setting for database"<<(*fSyncInfoListIterator).handheldDB;
00594 #endif
00595 break;
00596 }
00597 }
00598 }
00599
00600
00601 ResolutionDialog*dlg=new ResolutionDialog( 0, i18n("Conflict Resolution"), &fSyncInfoList , fHandle);
00602 bool show=DOCConduitSettings::alwaysShowResolutionDialog() || (dlg && dlg->hasConflicts);
00603 if (show) {
00604 if (!dlg || !dlg->exec() ) {
00605 KPILOT_DELETE(dlg)
00606 emit logMessage(i18n("Sync aborted by user."));
00607 QTimer::singleShot(0, this, SLOT(cleanup()));
00608 return;
00609 }
00610 }
00611 KPILOT_DELETE(dlg)
00612
00613
00614
00615 fDBNames.clear();
00616 fSyncInfoListIterator=fSyncInfoList.begin();
00617 QTimer::singleShot(0,this, SLOT(syncDatabases()));
00618 return;
00619 }
00620
00621
00622
00623 void DOCConduit::syncDatabases() {
00624 FUNCTIONSETUP;
00625 if (fSyncInfoListIterator==fSyncInfoList.end()) {
00626
00627 QTimer::singleShot(0, this, SLOT(cleanup()));
00628 return;
00629 }
00630
00631 docSyncInfo sinfo=(*fSyncInfoListIterator);
00632 ++fSyncInfoListIterator;
00633
00634 switch (sinfo.direction) {
00635 case eSyncConflict:
00636 break;
00637 case eSyncDelete:
00638 case eSyncPDAToPC:
00639 case eSyncPCToPDA:
00640 emit logMessage(i18n("Synchronizing text \"%1\"",sinfo.handheldDB));
00641 if (!doSync(sinfo)) {
00642
00643 DEBUGKPILOT << "There was some error syncing ["
00644 << sinfo.handheldDB
00645 << "] with file ["
00646 << sinfo.txtfilename << ']';
00647 }
00648 break;
00649 case eSyncNone:
00650 break;
00651 }
00652 if (sinfo.direction != eSyncDelete) fDBNames.append(sinfo.handheldDB);
00653
00654 QTimer::singleShot(0,this, SLOT(syncDatabases()));
00655 return;
00656 }
00657
00658
00659 PilotDatabase*DOCConduit::openDOCDatabase(const QString &dbname) {
00660 if (DOCConduitSettings::localSync())
00661 {
00662 return new PilotLocalDatabase(DOCConduitSettings::pDBDirectory(), dbname, false);
00663 }
00664 else
00665 {
00666 return deviceLink()->database( dbname );
00667 }
00668 }
00669
00670
00671 bool DOCConduit::needsSync(docSyncInfo &sinfo)
00672 {
00673 FUNCTIONSETUP;
00674 sinfo.direction = eSyncNone;
00675
00676 PilotDatabase*docdb=openDOCDatabase(QString::fromLatin1(sinfo.dbinfo.name));
00677 if (!fDBListSynced.contains(sinfo.handheldDB)) {
00678
00679 #ifdef DEBUG
00680 DEBUGKPILOT<<"Database"<<sinfo.dbinfo.name<<" was not included in the previous sync!";
00681 #endif
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691 if (QFile::exists(sinfo.txtfilename)) sinfo.fPCStatus=eStatNew;
00692 else sinfo.fPCStatus=eStatDoesntExist;
00693 if (docdb && docdb->isOpen()) sinfo.fPalmStatus=eStatNew;
00694 else sinfo.fPalmStatus=eStatDoesntExist;
00695 KPILOT_DELETE(docdb);
00696
00697 switch (eSyncDirection) {
00698 case eSyncPDAToPC:
00699 if (sinfo.fPalmStatus==eStatDoesntExist)
00700 sinfo.direction=eSyncDelete;
00701 else sinfo.direction=eSyncPDAToPC;
00702 break;
00703 case eSyncPCToPDA:
00704 if (sinfo.fPCStatus==eStatDoesntExist)
00705 sinfo.direction=eSyncDelete;
00706 else sinfo.direction=eSyncPCToPDA;
00707 break;
00708 case eSyncNone:
00709 if (sinfo.fPCStatus==eStatNew) {
00710 if (sinfo.fPalmStatus==eStatNew) sinfo.direction=eSyncConflict;
00711 else sinfo.direction=eSyncPCToPDA;
00712 } else {
00713 if (sinfo.fPalmStatus==eStatNew) sinfo.direction=eSyncPDAToPC;
00714 else {
00715 sinfo.direction=eSyncNone;
00716 }
00717 }
00718 break;
00719 default:
00720 break;
00721 }
00722 return true;
00723 }
00724
00725
00726 if (!QFile::exists(sinfo.txtfilename)) sinfo.fPCStatus=eStatDeleted;
00727 else if(pcTextChanged(sinfo.txtfilename)) {
00728 sinfo.fPCStatus=eStatChanged;
00729 #ifdef DEBUG
00730 DEBUGKPILOT<<"PC side has changed!";
00731 #endif
00732
00733 #ifdef DEBUG
00734 } else {
00735 DEBUGKPILOT<<"PC side has NOT changed!";
00736 #endif
00737 }
00738
00739 if (!docdb || !docdb->isOpen()) sinfo.fPalmStatus=eStatDeleted;
00740 else if (hhTextChanged(docdb)) {
00741 #ifdef DEBUG
00742 DEBUGKPILOT<<"Handheld side has changed!";
00743 #endif
00744 sinfo.fPalmStatus=eStatChanged;
00745 #ifdef DEBUG
00746 } else {
00747 DEBUGKPILOT<<"Handheld side has NOT changed!";
00748 #endif
00749 }
00750 KPILOT_DELETE(docdb);
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770 if (sinfo.fPCStatus == eStatNone && sinfo.fPalmStatus==eStatNone) {
00771 #ifdef DEBUG
00772 DEBUGKPILOT<<"Nothing has changed, not need for a sync.";
00773 #endif
00774 sinfo.direction=eSyncNone;
00775 return false;
00776 }
00777
00778
00779
00780
00781
00782 if (eSyncDirection==eSyncPCToPDA) {
00783 if (sinfo.fPCStatus==eStatDeleted) sinfo.direction=eSyncDelete;
00784 else sinfo.direction=eSyncPCToPDA;
00785 return true;
00786 }
00787 if (eSyncDirection==eSyncPDAToPC) {
00788 if (sinfo.fPalmStatus==eStatDeleted) sinfo.direction=eSyncDelete;
00789 else sinfo.direction=eSyncPDAToPC;
00790 return true;
00791 }
00792
00793
00794
00795
00796
00797
00798
00799
00800 if ( ((sinfo.fPCStatus==eStatDeleted) && (sinfo.fPalmStatus!=eStatChanged)) ||
00801 ((sinfo.fPalmStatus==eStatDeleted) && (sinfo.fPCStatus!=eStatChanged)) )
00802 {
00803 DEBUGKPILOT << "DB was deleted on one side and not changed on the other -> Delete it.";
00804 sinfo.direction=eSyncDelete;
00805 return true;
00806 }
00807
00808
00809
00810 if (sinfo.fPCStatus==eStatNone) {
00811 DEBUGKPILOT << "PC side has changed!";
00812 sinfo.direction=eSyncPDAToPC;
00813 return true;
00814 }
00815
00816 if (sinfo.fPalmStatus==eStatNone) {
00817 sinfo.direction=eSyncPCToPDA;
00818 return true;
00819 }
00820
00821
00822
00823
00824 sinfo.direction=eSyncConflict;
00825 return true;
00826 }
00827
00828
00829
00830 PilotDatabase *DOCConduit::preSyncAction(docSyncInfo &sinfo) const
00831 {
00832 FUNCTIONSETUP;
00833
00834 {
00835
00836 QDir dir( DOCConduitSettings::tXTDirectory() );
00837 if (!dir.exists())
00838 {
00839 dir.mkdir(dir.absPath());
00840 }
00841 }
00842
00843 DBInfo dbinfo=sinfo.dbinfo;
00844 switch (sinfo.direction)
00845 {
00846 case eSyncPDAToPC:
00847 if (DOCConduitSettings::keepPDBsLocally())
00848 {
00849
00850 QDir dir(DOCConduitSettings::pDBDirectory());
00851
00852 if (!dir.exists())
00853 {
00854 dir.mkdir(dir.absPath());
00855 }
00856 DEBUGKPILOT << "Need to fetch database "
00857 << dbinfo.name
00858 << " to the directory ["
00859 << dir.absPath() << ']';
00860 dbinfo.flags &= ~dlpDBFlagOpen;
00861
00862 if (!fHandle->retrieveDatabase(sinfo.pdbfilename, &dbinfo) )
00863 {
00864 WARNINGKPILOT << "Unable to retrieve database"
00865 << dbinfo.name
00866 << " from the handheld into ["
00867 << sinfo.pdbfilename << ']';
00868 return 0L;
00869 }
00870 }
00871 break;
00872 case eSyncPCToPDA:
00873 if (DOCConduitSettings::keepPDBsLocally())
00874 {
00875
00876 QDir dir(DOCConduitSettings::pDBDirectory());
00877 if (!dir.exists())
00878 {
00879 dir.mkdir(dir.absPath());
00880 }
00881 }
00882 break;
00883 default:
00884 break;
00885 }
00886 if (DOCConduitSettings::keepPDBsLocally())
00887 {
00888 return new PilotLocalDatabase(DOCConduitSettings::pDBDirectory(),
00889 QString::fromLatin1(dbinfo.name), false);
00890 }
00891 else
00892 {
00893 return deviceLink()->database(QString::fromLatin1(dbinfo.name));
00894 }
00895 }
00896
00897
00898
00899
00900 bool DOCConduit::postSyncAction(PilotDatabase * database,
00901 docSyncInfo &sinfo, bool res)
00902 {
00903 FUNCTIONSETUP;
00904 bool rs = true;
00905
00906 switch (sinfo.direction)
00907 {
00908 case eSyncPDAToPC:
00909
00910 DEBUGKPILOT << "Resetting sync flags for database ["
00911 << sinfo.dbinfo.name << ']';
00912 if (