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