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