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 #include "options.h"
00036
00037 #include <time.h>
00038 #include <unistd.h>
00039 #include <stdio.h>
00040
00041 #include <pi-file.h>
00042 #include <pi-util.h>
00043
00044 #include <qtimer.h>
00045 #include <qfile.h>
00046 #include <qfileinfo.h>
00047 #include <qdir.h>
00048 #include <qvaluelist.h>
00049 #include <qregexp.h>
00050 #include <qstringlist.h>
00051 #include <qthread.h>
00052
00053 #include <kglobal.h>
00054 #include <kstandarddirs.h>
00055 #include <kapplication.h>
00056 #include <kmessagebox.h>
00057
00058 #include "pilotUser.h"
00059 #include "pilotRecord.h"
00060 #include "actionQueue.h"
00061 #include "pilotSerialDatabase.h"
00062 #include "pilotLocalDatabase.h"
00063 #include "pilotDatabase.h"
00064 #include "kpilotSettings.h"
00065
00066 #include "hotSync.moc"
00067
00068 class BackupAction::Thread : public QThread
00069 {
00070 public:
00071 Thread( BackupAction *parent,
00072 KPilotLink *link,
00073 const QString &filename,
00074 const DBInfo *info );
00075
00076 enum {
00077 TerminateOK = QEvent::User,
00078 TerminateFailure
00079 } ;
00080
00081 protected:
00082 virtual void run();
00083 private:
00084 BackupAction *fParent;
00085 KPilotLink *fLink;
00086 QString fFilename;
00087 struct DBInfo fDBInfo;
00088 } ;
00089
00090 class BackupAction::Private
00091 {
00092 public:
00093 bool fFullBackup;
00094 QStringList fNoBackupDBs;
00095 QValueList<unsigned long> fNoBackupCreators;
00096 QStringList fDeviceDBs;
00097
00098 QString fPreferBackupDir;
00099
00100
00101
00102 int fDBIndex;
00103 QString fBackupDir;
00104
00109 void addDBInfo( const DBInfo *info )
00110 {
00111 FUNCTIONSETUP;
00112 fDBIndex = info->index + 1;
00113
00114
00115 char buff[7];
00116 buff[0] = '[';
00117 set_long( &buff[1], info->creator );
00118 buff[5] = ']';
00119 buff[6] = '\0';
00120 QString creator = QString::fromLatin1( buff );
00121
00122 QString dbname = Pilot::fromPilot( info->name, 32 );
00123
00124 if ( !fDeviceDBs.contains( creator ) )
00125 {
00126 fDeviceDBs << creator;
00127 }
00128 if ( !fDeviceDBs.contains( dbname ) )
00129 {
00130 fDeviceDBs << dbname;
00131 }
00132
00133 DEBUGKPILOT << fname << ": Added <" << dbname
00134 << "> " << creator << endl;
00135 }
00136
00137
00145 bool allowBackup( const DBInfo *info ) const
00146 {
00147
00148 if ( (info->creator == pi_mktag('p','s','y','s')) &&
00149 (info->type == pi_mktag('p','r','e','f')) )
00150 {
00151 return false;
00152 }
00153
00154 if (fNoBackupCreators.findIndex(info->creator) != -1)
00155 {
00156 return false;
00157 }
00158
00159
00160 QString db = Pilot::fromPilot(info->name);
00161 for (QStringList::const_iterator i = fNoBackupDBs.begin();
00162 i != fNoBackupDBs.end(); ++i)
00163 {
00164 QRegExp re(*i,true,true);
00165 if (re.exactMatch(db))
00166 {
00167 return false;
00168 }
00169 }
00170 return true;
00171 }
00172
00173 } ;
00174
00175 BackupAction::BackupAction(KPilotLink * p, bool full) :
00176 SyncAction(p, "backupAction"),
00177 fP( new Private ),
00178 fBackupThread( 0L )
00179 {
00180 FUNCTIONSETUP;
00181
00182 fP->fFullBackup = full;
00183 }
00184
00185 QString BackupAction::statusString() const
00186 {
00187 FUNCTIONSETUP;
00188 QString s(CSL1("BackupAction="));
00189
00190 switch (status())
00191 {
00192 case Init:
00193 s.append(CSL1("Init"));
00194 break;
00195 case Error:
00196 s.append(CSL1("Error"));
00197 break;
00198 case FullBackup:
00199 s.append(CSL1("FullBackup"));
00200 break;
00201 case FastBackup:
00202 s.append(CSL1("FastBackup"));
00203 break;
00204 case BackupEnded:
00205 s.append(CSL1("BackupEnded"));
00206 break;
00207 case BackupIncomplete:
00208 s.append(CSL1("BackupIncomplete"));
00209 break;
00210 case BackupComplete:
00211 s.append(CSL1("BackupComplete"));
00212 break;
00213 default:
00214 s.append(CSL1("(unknown "));
00215 s.append(QString::number(status()));
00216 s.append(CSL1(")"));
00217 }
00218
00219 return s;
00220 }
00221
00222 void BackupAction::setDirectory( const QString &p )
00223 {
00224 fP->fPreferBackupDir = p;
00225 if (!p.endsWith(CSL1("/")))
00226 {
00227 fP->fPreferBackupDir.append(CSL1("/"));
00228 }
00229 }
00230
00231 static inline void initNoBackup(QStringList &dbnames,
00232 QValueList<unsigned long> &dbcreators)
00233 {
00234 FUNCTIONSETUP;
00235 dbnames.clear();
00236 dbcreators.clear();
00237
00238 QStringList configuredSkip = KPilotSettings::skipBackupDB();
00239 QStringList::const_iterator e = configuredSkip.end();
00240 for (QStringList::const_iterator i = configuredSkip.begin();
00241 i!= e; ++i)
00242 {
00243 QString s = *i;
00244 if (s.startsWith(CSL1("[")) && s.endsWith(CSL1("]")))
00245 {
00246 if (s.length() != 6)
00247 {
00248 WARNINGKPILOT << "Creator ID " << s << " is malformed." << endl;
00249 }
00250 else
00251 {
00252 QCString data = s.mid(1,4).latin1();
00253 unsigned long creator = pi_mktag(data[0],data[1],data[2],data[3]);
00254 dbcreators.append(creator);
00255 }
00256 }
00257 else
00258 {
00259 dbnames.append(s);
00260 }
00261 }
00262
00263 DEBUGKPILOT << fname << ": Will skip databases "
00264 << dbnames.join(CSL1(",")) << endl;
00265 QString creatorids;
00266 char buf[5];
00267 for (QValueList<unsigned long>::const_iterator i = dbcreators.begin();
00268 i != dbcreators.end(); ++i)
00269 {
00270 unsigned long tag = *i;
00271 pi_untag(buf,tag);
00272 buf[4]=0;
00273 creatorids.append(CSL1("[%1]").arg(buf));
00274 }
00275 DEBUGKPILOT << fname << ": Will skip creators " << creatorids << endl;
00276 }
00277
00283 static inline bool checkBackupDirectory( const QString &backupDir )
00284 {
00285 FUNCTIONSETUP;
00286 QFileInfo fi(backupDir);
00287
00288 if (fi.exists() && fi.isDir())
00289 {
00290 return true;
00291 }
00292
00293 if (fi.exists() && !fi.isDir())
00294 {
00295 WARNINGKPILOT << "Requested backup directory "
00296 << backupDir
00297 << " exists but is not a directory."
00298 << endl;
00299 return false;
00300 }
00301
00302 if ( !backupDir.endsWith("/") )
00303 {
00304 WARNINGKPILOT << "Backup dir does not end with a / "
00305 << endl;
00306 return false;
00307 }
00308
00309 Q_ASSERT(!fi.exists());
00310
00311 DEBUGKPILOT << fname
00312 << ": Creating directory " << backupDir << endl;
00313
00314 KStandardDirs::makeDir( backupDir );
00315
00316 fi = QFileInfo(backupDir);
00317
00318 return fi.exists() && fi.isDir();
00319 }
00320
00321
00322 bool BackupAction::exec()
00323 {
00324 FUNCTIONSETUP;
00325
00326 fP->fDeviceDBs = KPilotSettings::deviceDBs();
00327
00328 if (fP->fPreferBackupDir.isEmpty())
00329 {
00330 fP->fBackupDir =
00331 KGlobal::dirs()->saveLocation("data",CSL1("kpilot/DBBackup/")) +
00332 deviceLink()->getPilotUser().name() + '/';
00333 }
00334 else
00335 {
00336 fP->fBackupDir = fP->fPreferBackupDir;
00337 }
00338
00339 logMessage(i18n("Backup directory: %1.").arg(fP->fBackupDir));
00340
00341 DEBUGKPILOT << fname
00342 << ": This Pilot user's name is \""
00343 << deviceLink()->getPilotUser().name() << "\"" << endl;
00344 DEBUGKPILOT << fname
00345 << ": Using backup dir: " << fP->fBackupDir << endl;
00346 DEBUGKPILOT << fname
00347 << ": Full Backup? " << fP->fFullBackup << endl;
00348
00349
00350 if (fP->fFullBackup)
00351 {
00352 fActionStatus = FullBackup;
00353 addSyncLogEntry(i18n("Full backup started."));
00354 }
00355 else
00356 {
00357 fActionStatus = FastBackup;
00358 addSyncLogEntry(i18n("Fast backup started"));
00359 }
00360
00361 if (!checkBackupDirectory(fP->fBackupDir))
00362 {
00363 fActionStatus=BackupIncomplete;
00364
00365
00366 return false;
00367 }
00368
00369 initNoBackup( fP->fNoBackupDBs, fP->fNoBackupCreators );
00370
00371 fP->fDBIndex = 0;
00372 QTimer::singleShot(0,this,SLOT(backupOneDB()));
00373 return true;
00374 }
00375
00376 void BackupAction::backupOneDB()
00377 {
00378 FUNCTIONSETUP;
00379
00380 struct DBInfo info;
00381
00382
00383 emit logProgress(QString::null, fP->fDBIndex);
00384
00385 if (openConduit() < 0)
00386 {
00387 addSyncLogEntry(i18n("Exiting on cancel."));
00388 endBackup();
00389 fActionStatus = BackupIncomplete;
00390 return;
00391 }
00392
00393
00394 int res = deviceLink()->getNextDatabase( fP->fDBIndex, &info );
00395 if (res < 0)
00396 {
00397 if ( fP->fFullBackup )
00398 {
00399 addSyncLogEntry( i18n("Full backup complete.") );
00400 }
00401 else
00402 {
00403 addSyncLogEntry( i18n("Fast backup complete.") );
00404 }
00405 endBackup();
00406 fActionStatus = BackupComplete;
00407 return;
00408 }
00409
00410 fP->addDBInfo( &info );
00411
00412
00413 if (fP->allowBackup(&info))
00414 {
00415
00416
00417 if ( (fP->fFullBackup) || !PilotDatabase::isResource(&info) )
00418 {
00419 addSyncLogEntry(i18n("Backing up: %1").arg(Pilot::fromPilot(info.name)));
00420
00421 if (!startBackupThread(&info))
00422 {
00423 WARNINGKPILOT << "Could not create local database for <"
00424 << info.name << ">" << endl;
00425 }
00426 else
00427 {
00428
00429
00430
00431
00432
00433 return;
00434 }
00435 }
00436 else
00437 {
00438
00439 DEBUGKPILOT << fname << ": Skipping database <" << info.name
00440 << "> (resource database)" << endl;
00441 }
00442 }
00443 else
00444 {
00445 DEBUGKPILOT << fname << ": Skipping database <" << info.name
00446 << "> (no-backup list)" << endl;
00447 QString s = i18n("Skipping %1")
00448 .arg(Pilot::fromPilot(info.name));
00449 addSyncLogEntry(s);
00450 }
00451 QTimer::singleShot(0,this,SLOT(backupOneDB()));
00452 }
00453
00467 bool BackupAction::startBackupThread(DBInfo *info)
00468 {
00469 FUNCTIONSETUP;
00470
00471
00472
00473
00474 if (!fP->fFullBackup)
00475 {
00476
00477 PilotDatabase *serial=deviceLink()->database(info);
00478 if (!serial->isOpen())
00479 {
00480 WARNINGKPILOT << "Unable to open database <" << info->name << ">" << endl;
00481 KPILOT_DELETE(serial);
00482 addSyncLogEntry(i18n("Backup of %1 failed.\n")
00483 .arg(Pilot::fromPilot(info->name)));
00484 return false;
00485 }
00486
00487 int index=0;
00488 PilotRecord*rec=serial->readNextModifiedRec(&index);
00489 if (!rec)
00490 {
00491 DEBUGKPILOT << fname << ": No modified records." << endl;
00492 KPILOT_DELETE(serial);
00493 return false;
00494 }
00495
00496 KPILOT_DELETE(rec);
00497 KPILOT_DELETE(serial);
00498 }
00499
00500
00501
00502
00503 QString databaseName(Pilot::fromPilot(info->name));
00504 databaseName.replace('/', '_');
00505
00506 QString fullBackupName = fP->fBackupDir + databaseName;
00507
00508 if (PilotDatabase::isResource(info))
00509 {
00510 fullBackupName.append(CSL1(".prc"));
00511 }
00512 else
00513 {
00514 fullBackupName.append(CSL1(".pdb"));
00515 }
00516
00517 DEBUGKPILOT << fname
00518 << ": Backing up database to: [" << fullBackupName << "]" << endl;
00519
00520
00521 info->flags &= ~dlpDBFlagOpen;
00522
00523 if (fBackupThread)
00524 {
00525 WARNINGKPILOT << "Starting new backup thread before the old one is done." << endl;
00526 return false;
00527 }
00528
00529 fBackupThread = new Thread(this,deviceLink(),fullBackupName,info);
00530 fBackupThread->start();
00531 return true;
00532 }
00533
00534 bool BackupAction::event( QEvent *e )
00535 {
00536 if (e->type() == (QEvent::Type)Thread::TerminateOK)
00537 {
00538 KPILOT_DELETE(fBackupThread);
00539
00540 addSyncLogEntry( i18n("... OK.\n"), false );
00541 QTimer::singleShot(0,this,SLOT(backupOneDB()));
00542 return true;
00543 }
00544 if (e->type() == (QEvent::Type)Thread::TerminateFailure)
00545 {
00546 KPILOT_DELETE(fBackupThread);
00547
00548 addSyncLogEntry( i18n("Backup failed.") );
00549 QTimer::singleShot(0,this,SLOT(backupOneDB()));
00550 return true;
00551 }
00552 return SyncAction::event(e);
00553 }
00554
00555 void BackupAction::endBackup()
00556 {
00557 FUNCTIONSETUP;
00558
00559 fP->fDBIndex = (-1);
00560 fActionStatus = BackupEnded;
00561 fP->fDeviceDBs.sort();
00562 QString old( QString::null );
00563 QStringList::Iterator itr = fP->fDeviceDBs.begin();
00564 while ( itr != fP->fDeviceDBs.end() ) {
00565 if ( old == *itr ) {
00566 itr = fP->fDeviceDBs.remove( itr );
00567 } else {
00568 old = *itr;
00569 ++itr;
00570 }
00571 }
00572 KPilotSettings::setDeviceDBs( fP->fDeviceDBs );
00573
00574 emit syncDone(this);
00575 }
00576
00577 FileInstallAction::FileInstallAction(KPilotLink * p,
00578 const QString & d) :
00579 SyncAction(p, "fileInstall"),
00580 fDBIndex(-1),
00581 fTimer(0L),
00582 fDir(d)
00583 {
00584 FUNCTIONSETUP;
00585 }
00586
00587 FileInstallAction::~FileInstallAction()
00588 {
00589 FUNCTIONSETUP;
00590
00591 KPILOT_DELETE(fTimer);
00592 }
00593
00594 bool FileInstallAction::exec()
00595 {
00596 FUNCTIONSETUP;
00597
00598 QDir installDir(fDir);
00599 fList = installDir.entryList(QDir::Files |
00600 QDir::NoSymLinks | QDir::Readable);
00601 #ifdef DEBUG
00602 DEBUGKPILOT << fname
00603 << ": Installing " << fList.count() << " files" << endl;
00604 #endif
00605
00606 fDBIndex = 0;
00607 emit logMessage(i18n("[File Installer]"));
00608
00609
00610 if (!fList.count())
00611 {
00612 emit logMessage(i18n("No Files to install"));
00613 delayDone();
00614 return true;
00615 }
00616
00617 fTimer = new QTimer(this);
00618 QObject::connect(fTimer, SIGNAL(timeout()),
00619 this, SLOT(installNextFile()));
00620
00621 fTimer->start(0, false);
00622
00623 emit logProgress(i18n("Installing one file",
00624 "Installing %n Files",fList.count()), 0);
00625 return true;
00626 }
00627
00628 void FileInstallAction::installNextFile()
00629 {
00630 FUNCTIONSETUP;
00631
00632 Q_ASSERT(fDBIndex >= 0);
00633 Q_ASSERT((unsigned) fDBIndex <= fList.count());
00634
00635 #ifdef DEBUG
00636 DEBUGKPILOT << fname
00637 << ": Installing file index "
00638 << fDBIndex << " (of " << fList.count() << ")" << endl;
00639 #endif
00640
00641 if ((!fList.count()) || ((unsigned) fDBIndex >= fList.count()))
00642 {
00643 #ifdef DEBUG
00644 DEBUGKPILOT << fname
00645 << ": Peculiar file index, bailing out." << endl;
00646 #endif
00647 KPILOT_DELETE(fTimer);
00648 fDBIndex = (-1);
00649 emit logProgress(i18n("Done Installing Files"), 100);
00650 delayDone();
00651 return;
00652 }
00653
00654 const QString filePath = fDir + fList[fDBIndex];
00655 const QString fileName = fList[fDBIndex];
00656
00657 fDBIndex++;
00658
00659 #ifdef DEBUG
00660 DEBUGKPILOT << fname << ": Installing file " << filePath << endl;
00661 #endif
00662
00663 QString m = i18n("Installing %1").arg(fileName);
00664 emit logProgress(m,(100 * fDBIndex) / (fList.count()+1));
00665 m+=CSL1("\n");
00666 emit addSyncLogEntry(m,false );
00667
00668 struct pi_file *f = 0L;
00669
00670
00671 if (!resourceOK(fileName,filePath)) goto nextFile;
00672
00673 f = pi_file_open(const_cast <char *>
00674 ((const char *) QFile::encodeName(filePath)));
00675
00676
00677 #if PILOT_LINK_NUMBER < PILOT_LINK_0_12_0
00678 if (pi_file_install(f, pilotSocket(), 0) < 0)
00679 #else
00680 if (pi_file_install(f, pilotSocket(), 0, NULL) < 0)
00681 #endif
00682 {
00683 WARNINGKPILOT << "Failed to install." << endl;
00684
00685
00686 emit logError(i18n("Cannot install file "%1".").
00687 arg(fileName));
00688 }
00689 else
00690 {
00691 QFile::remove(filePath);
00692 }
00693
00694
00695 nextFile:
00696 if (f) pi_file_close(f);
00697 if (fDBIndex == -1)
00698 {
00699 fTimer->stop();
00700 delayDone();
00701
00702 }
00703 }
00704
00705
00706
00707 bool FileInstallAction::resourceOK(const QString &fileName, const QString &filePath)
00708 {
00709 FUNCTIONSETUP;
00710
00711 if (!QFile::exists(filePath))
00712 {
00713 emit logError(i18n("Unable to open file "%1".").
00714 arg(fileName));
00715 return false;
00716 }
00717
00718 struct pi_file *f = pi_file_open(const_cast <char *>
00719 ((const char *) QFile::encodeName(filePath)));
00720
00721 if (!f)
00722 {
00723 emit logError(i18n("Unable to open file "%1".").
00724 arg(fileName));
00725 return false;
00726 }
00727
00728 struct DBInfo info;
00729 #if PILOT_LINK_NUMBER < PILOT_LINK_0_12_0
00730 if (pi_file_get_info(f,&info) < 0)
00731 {
00732 emit logError(i18n("Unable to read file "%1".").
00733 arg(fileName));
00734 return false;
00735 }
00736 #else
00737 pi_file_get_info(f,&info);
00738 #endif
00739
00740
00741
00742 info.name[sizeof(info.name)-1]=0;
00743 bool r = (strlen(info.name) < 32);
00744 pi_file_close(f);
00745
00746 if (!r)
00747 {
00748 emit logError(i18n("The database in "%1" has a "
00749 "resource name that is longer than 31 characters. "
00750 "This suggests a bug in the tool used to create the database. "
00751 "KPilot cannot install this database.").arg(fileName));
00752 }
00753
00754 return r;
00755 }
00756
00757 QString FileInstallAction::statusString() const
00758 {
00759 FUNCTIONSETUP;
00760 if (fDBIndex < 0)
00761 {
00762 return QString(CSL1("Idle"));
00763 }
00764 else
00765 {
00766 if ((unsigned) fDBIndex >= fList.count())
00767 {
00768 return QString(CSL1("Index out of range"));
00769 }
00770 else
00771 {
00772 return QString(CSL1("Installing %1")).arg(fList[fDBIndex]);
00773 }
00774 }
00775 }
00776
00777 CheckUser::CheckUser(KPilotLink * p, QWidget * vp):
00778 SyncAction(p, vp, "userCheck")
00779 {
00780 FUNCTIONSETUP;
00781
00782 }
00783
00784 CheckUser::~CheckUser()
00785 {
00786 FUNCTIONSETUP;
00787 }
00788
00789 bool CheckUser::exec()
00790 {
00791 FUNCTIONSETUP;
00792
00793 QString guiUserName = KPilotSettings::userName();
00794 QString pilotUserName = fHandle->getPilotUser().name();
00795 bool pilotUserEmpty = pilotUserName.isEmpty();
00796
00797
00798
00799
00800
00801 if (guiUserName.isEmpty())
00802 {
00803 if (pilotUserEmpty)
00804 {
00805 QString defaultUserName =
00806 i18n("A common name", "John Doe");
00807
00808 QString q = i18n("<qt>Neither KPilot nor the "
00809 "handheld have a username set. "
00810 "They <i>should</i> be set. "
00811 "Should KPilot set them to a default value "
00812 "(<i>%1</i>)?</qt>").arg(defaultUserName);
00813
00814 if (questionYesNo(q, i18n("User Unknown") ) ==
00815 KMessageBox::Yes)
00816 {
00817 KPilotSettings::setUserName(defaultUserName);
00818 fHandle->getPilotUser().setName(defaultUserName);
00819 guiUserName=defaultUserName;
00820 pilotUserName=defaultUserName;
00821 }
00822
00823 }
00824 else
00825 {
00826 QString q = i18n("<qt>The handheld has a username set "
00827 "(<i>%1</i>) but KPilot does not. Should "
00828 "KPilot use this username in future?</qt>").
00829 arg(pilotUserName);
00830
00831 if (questionYesNo(q, i18n("User Unknown") ) ==
00832 KMessageBox::Yes)
00833 {
00834 KPilotSettings::setUserName(pilotUserName);
00835 guiUserName=pilotUserName;
00836 }
00837 }
00838 }
00839 else
00840 {
00841 if (pilotUserEmpty)
00842 {
00843 QString q = CSL1("<qt>");
00844 q += i18n("KPilot has a username set "
00845 "(<i>%1</i>) but the handheld does not. "
00846 "Should KPilot's username be set in the "
00847 "handheld as well?").arg(guiUserName);
00848 q += i18n("<br/>(<i>Note:</i> If your handheld "
00849 "has been reset to factory defaults, you "
00850 "should use <i>Restore</i> instead of a "
00851 "regular HotSync. Click on Cancel to "
00852 "stop this sync.)");
00853 q += CSL1("</qt>");
00854
00855 int r = questionYesNoCancel(q, i18n("User Unknown"));
00856 switch (r)
00857 {
00858 case KMessageBox::Yes:
00859 DEBUGKPILOT << fname
00860 << ": Setting user name in pilot to "
00861 << guiUserName << endl;
00862 fHandle->getPilotUser().setName(guiUserName);
00863 pilotUserName=guiUserName;
00864 break;
00865 case KMessageBox::No:
00866
00867 break;
00868 case KMessageBox::Cancel:
00869 default:
00870 return false;
00871 }
00872 }
00873 else
00874 {
00875 if (guiUserName != pilotUserName)
00876 {
00877 QString q = i18n("<qt>The handheld thinks that "
00878 "the username is %1; "
00879 "however, KPilot says you are %2."
00880 "Which of these is the correct name?\n"
00881 "If you click on Cancel, the sync will proceed, "
00882 "but the usernames will not be changed.</qt>").
00883 arg(pilotUserName).
00884 arg(guiUserName);
00885
00886 int r = questionYesNoCancel(q,
00887 i18n("User Mismatch"),
00888 QString::null,
00889 20,
00890 i18n("Use KPilot Name"),
00891 i18n("Use Handheld Name"));
00892 switch (r)
00893 {
00894 case KMessageBox::Yes:
00895 fHandle->getPilotUser().setName(guiUserName);
00896 pilotUserName=guiUserName;
00897 break;
00898 case KMessageBox::No:
00899 KPilotSettings::setUserName(pilotUserName);
00900 guiUserName=pilotUserName;
00901 break;
00902 case KMessageBox::Cancel:
00903 default:
00904
00905 break;
00906 }
00907 }
00908 }
00909 }
00910
00911
00912 #ifdef DEBUG
00913 DEBUGKPILOT << fname
00914 << ": User name set to pc <"
00915 << guiUserName
00916 << "> hh <"
00917 << fHandle->getPilotUser().name() << ">" << endl;
00918 #endif
00919
00920 KPilotSettings::writeConfig();
00921
00922
00923
00924
00925
00926 QString pathName = KGlobal::dirs()->saveLocation("data",
00927 CSL1("kpilot/DBBackup/"));
00928 if (!guiUserName.isEmpty())
00929 {
00930 pathName.append(guiUserName);
00931 pathName.append(CSL1("/"));
00932 }
00933 PilotLocalDatabase::setDBPath(pathName);
00934
00935 delayDone();
00936 return true;
00937 }
00938
00939 class RestoreInfo
00940 {
00941 public:
00942 struct DBInfo DBInfo;
00943 QString path;
00944 } ;
00945
00946 class RestoreAction::Private
00947 {
00948 public:
00949 QString fPreferRestoreDir;
00951 QValueList<RestoreInfo> fDBList;
00952 QTimer fTimer;
00953 QValueList<RestoreInfo>::ConstIterator fDBIterator;
00954 int fDBIndex;
00955 };
00956
00957
00958 RestoreAction::RestoreAction(KPilotLink * p, QWidget * visible ) :
00959 SyncAction(p, visible, "restoreAction")
00960 {
00961 FUNCTIONSETUP;
00962
00963 fP = new Private;
00964 }
00965
00966 void RestoreAction::setDirectory( const QString &path )
00967 {
00968 fP->fPreferRestoreDir = path;
00969 }
00970
00971 bool RestoreAction::exec()
00972 {
00973 FUNCTIONSETUP;
00974
00975 QString dirname;
00976 if (fP->fPreferRestoreDir.isEmpty())
00977 {
00978 dirname = PilotLocalDatabase::getDBPath();
00979 }
00980 else
00981 {
00982 dirname = fP->fPreferRestoreDir;
00983 }
00984
00985 #ifdef DEBUG
00986 DEBUGKPILOT << fname << ": Restoring user " << dirname << endl;
00987 #endif
00988
00989 QDir dir(dirname, QString::null, QDir::Name,
00990 QDir::Files | QDir::Readable | QDir::NoSymLinks);
00991
00992 if (!dir.exists())
00993 {
00994 WARNINGKPILOT << "Restore directory "
00995 << dirname << " does not exist." << endl;
00996 fActionStatus = Error;
00997 addSyncLogEntry(i18n("Restore directory does not exist.") +
00998 CSL1(" ") + i18n("Restore not performed."));
00999 return false;
01000 }
01001
01002 dirname = dir.absPath();
01003 if (questionYesNo(i18n("<qt>Are you sure you want to completely "
01004 "restore your Pilot from the backup directory "
01005 "(<i>%1</i>)? This will erase any information "
01006 "you currently have on your Pilot.</qt>").
01007 arg(dirname),
01008 i18n("Restore Pilot")) != KMessageBox::Yes)
01009 {
01010 emit logError(i18n("Restore <i>not</i> performed."));
01011
01012 addSyncLogEntry(i18n("Canceled by user.") + CSL1(" ") +
01013 i18n("Restore not performed."));
01014
01015
01016
01017
01018
01019 delayDone();
01020 return true;
01021 }
01022
01023
01024 emit logProgress(i18n("Restoring %1...").arg(QString::null),1);
01025
01026 for (unsigned int i = 0; i < dir.count(); i++)
01027 {
01028 QString s;
01029 RestoreInfo info;
01030
01031 s = dirname + QDir::separator() + dir[i];
01032
01033 DEBUGKPILOT << fname
01034 << ": Adding " << s << " to restore list." << endl;
01035
01036 if ( PilotLocalDatabase::infoFromFile( s, &info.DBInfo ) )
01037 {
01038 info.path = s;
01039 fP->fDBList.append(info);
01040 }
01041 else
01042 {
01043 WARNINGKPILOT << "Can't open " << s << endl;
01044 logMessage(i18n("File '%1' cannot be read.").arg(s));
01045 }
01046 }
01047
01048 fP->fDBIndex = 0;
01049 fP->fDBIterator = fP->fDBList.begin();
01050 fActionStatus = InstallingFiles;
01051
01052 QObject::connect(&(fP->fTimer), SIGNAL(timeout()),
01053 this, SLOT(installNextFile()));
01054
01055 fP->fTimer.start(0, false);
01056 return true;
01057 }
01058
01059 void RestoreAction::installNextFile()
01060 {
01061 FUNCTIONSETUP;
01062
01063 Q_ASSERT(fActionStatus == InstallingFiles);
01064
01065
01066 if (fP->fDBIterator == fP->fDBList.end())
01067 {
01068 fP->fTimer.stop();
01069
01070 fActionStatus = Done;
01071 addSyncLogEntry(i18n("OK."));
01072 delayDone();
01073 return;
01074 }
01075
01076 const RestoreInfo dbi = *(fP->fDBIterator);
01077 ++(fP->fDBIterator);
01078 ++(fP->fDBIndex);
01079
01080 DEBUGKPILOT << fname << ": Trying to install " << dbi.path << endl;
01081
01082 if (openConduit() < 0)
01083 {
01084 WARNINGKPILOT << "Restore apparently canceled." << endl;
01085 logMessage(i18n("Restore incomplete."));
01086 fActionStatus = Done;
01087 emit syncDone(this);
01088
01089 return;
01090 }
01091
01092 QFileInfo databaseInfo(dbi.path);
01093 addSyncLogEntry(databaseInfo.fileName());
01094 emit logProgress(i18n("Restoring %1...").arg(databaseInfo.fileName()),
01095 (100*fP->fDBIndex) / (fP->fDBList.count()+1)) ;
01096
01097 if ( !deviceLink()->installFiles( dbi.path, false ) )
01098 {
01099 WARNINGKPILOT << "Couldn't restore " << dbi.path << endl;
01100 logError(i18n("Cannot restore file `%1'.")
01101 .arg(databaseInfo.fileName()));
01102 }
01103 }
01104
01105 QString RestoreAction::statusString() const
01106 {
01107 FUNCTIONSETUP;
01108 QString s;
01109
01110 switch (status())
01111 {
01112 case InstallingFiles:
01113 s.append(CSL1("Installing Files ("));
01114 s.append(QString::number(fP->fDBIndex));
01115 s.append(CSL1(")"));
01116 break;
01117 case GettingFileInfo:
01118 s.append(CSL1("Getting File Info ("));
01119 s.append(QString::number(fP->fDBIndex));
01120 s.append(CSL1(")"));
01121 break;
01122 default:
01123 return SyncAction::statusString();
01124 }
01125
01126 return s;
01127 }
01128
01129
01130
01131 BackupAction::Thread::Thread( BackupAction *parent,
01132 KPilotLink *link,
01133 const QString &filename,
01134 const DBInfo *info )
01135 {
01136 fParent = parent;
01137 fLink = link;
01138 fFilename = filename;
01139 memcpy(&fDBInfo,info,sizeof(DBInfo));
01140 }
01141
01142 void BackupAction::Thread::run()
01143 {
01144 if (fLink->retrieveDatabase(fFilename,&fDBInfo))
01145 {
01146
01147 QApplication::postEvent( fParent, new QEvent( (QEvent::Type)TerminateOK ) );
01148 }
01149 else
01150 {
01151
01152 QApplication::postEvent( fParent, new QEvent( (QEvent::Type)TerminateFailure ) );
01153 }
01154 }
01155
01156