kpilot/kpilot

interactiveSync.cc

00001 /* KPilot
00002 **
00003 ** Copyright (C) 2001 by Dan Pilone
00004 ** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005 ** Copyright (C) 2006 Adriaan de Groot <groot@kde.org>
00006 **
00007 ** This file specializes SyncAction to a kind that can have interaction
00008 ** with the user without the Sync timing out.
00009 */
00010 
00011 /*
00012 ** This program is free software; you can redistribute it and/or modify
00013 ** it under the terms of the GNU General Public License as published by
00014 ** the Free Software Foundation; either version 2 of the License, or
00015 ** (at your option) any later version.
00016 **
00017 ** This program is distributed in the hope that it will be useful,
00018 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00020 ** GNU General Public License for more details.
00021 **
00022 ** You should have received a copy of the GNU General Public License
00023 ** along with this program in a file called COPYING; if not, write to
00024 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00025 ** MA 02110-1301, USA.
00026 */
00027 
00028 /*
00029 ** Bug reports and questions can be sent to kde-pim@kde.org.
00030 */
00031 
00032 #include "options.h"
00033 
00034 #include <time.h>
00035 #include <unistd.h>
00036 #include <stdio.h>
00037 
00038 #include <pi-socket.h>
00039 #include <pi-file.h>
00040 
00041 #include <qtimer.h>
00042 #include <qvbox.h>
00043 #include <qlayout.h>
00044 #include <qlabel.h>
00045 #include <qmessagebox.h>
00046 #include <qdir.h>
00047 #include <qfile.h>
00048 #include <qfileinfo.h>
00049 #include <qtl.h>
00050 #include <qstyle.h>
00051 
00052 #include <kdialogbase.h>
00053 #include <kglobal.h>
00054 #include <kstandarddirs.h>
00055 #include <kmessagebox.h>
00056 
00057 #include <kapplication.h>
00058 
00059 #include "pilotUser.h"
00060 #include "pilotRecord.h"
00061 #include "pilotLocalDatabase.h"
00062 #include "kpilotConfig.h"
00063 #include "kpilotlink.h"
00064 
00065 #include "interactiveSync.moc"
00066 
00067 
00068 CheckUser::CheckUser(KPilotLink * p, QWidget * vp):
00069     SyncAction(p, vp, "userCheck")
00070 {
00071     FUNCTIONSETUP;
00072 
00073 }
00074 
00075 CheckUser::~CheckUser()
00076 {
00077     FUNCTIONSETUP;
00078 }
00079 
00080 /* virtual */ bool CheckUser::exec()
00081 {
00082     FUNCTIONSETUP;
00083 
00084     QString guiUserName = KPilotSettings::userName();
00085 // TODO: add userName() to pilotUser class
00086     QString pilotUserName = Pilot::fromPilot(fHandle->getPilotUser().getUserName());
00087     bool pilotUserEmpty = pilotUserName.isEmpty();
00088     // 4 cases to handle:
00089     //    guiUserName empty / not empty
00090     //    pilotUserName empty / not empty
00091     //
00092     //
00093     if (guiUserName.isEmpty())
00094     {
00095         if (pilotUserEmpty)
00096         {
00097             QString defaultUserName =
00098                 i18n("A common name", "John Doe");
00099 
00100             QString q = i18n("<qt>Neither KPilot nor the "
00101                 "handheld have a username set. "
00102                 "They <i>should</i> be set. "
00103                 "Should KPilot set them to a default value "
00104                 "(<i>%1</i>)?</qt>").arg(defaultUserName);
00105 
00106             if (questionYesNo(q, i18n("User Unknown") /* ,"askUserNone" */) ==
00107                 KMessageBox::Yes)
00108             {
00109                 KPilotSettings::setUserName(defaultUserName);
00110                 fHandle->getPilotUser()
00111                     .setUserName(Pilot::toPilot(defaultUserName));
00112                 guiUserName=defaultUserName;
00113                 pilotUserName=defaultUserName;
00114             }
00115 
00116         }
00117         else
00118         {
00119             QString q = i18n("<qt>The handheld has a username set "
00120                 "(<i>%1</i>) but KPilot does not. Should "
00121                 "KPilot use this username in future?").
00122                 arg(pilotUserName);
00123 
00124             if (questionYesNo(q, i18n("User Unknown") /* ,"askUserSome" */ ) ==
00125                 KMessageBox::Yes)
00126             {
00127                 KPilotSettings::setUserName(pilotUserName);
00128                 guiUserName=pilotUserName;
00129             }
00130         }
00131     }
00132     else
00133     {
00134         if (pilotUserEmpty)
00135         {
00136             QString q = i18n("<qt>KPilot has a username set "
00137                 "(<i>%1</i>) but the handheld does not. "
00138                 "Should KPilot's username be set in the "
00139                 "handheld as well?").arg(guiUserName);
00140 
00141             if (questionYesNo(q, i18n("User Unknown") /* ,"askUserSome" */) ==
00142                 KMessageBox::Yes)
00143             {
00144 #ifdef DEBUG
00145                 DEBUGKPILOT << fname
00146                     << ": Setting user name in pilot to "
00147                     << guiUserName << endl;
00148 #endif
00149 
00150                 QCString l1 = Pilot::toPilot(guiUserName);
00151 
00152                 fHandle->getPilotUser().setUserName(l1.data());
00153                 pilotUserName=guiUserName;
00154             }
00155         }
00156         else
00157         {
00158             if (guiUserName != pilotUserName)
00159             {
00160                 QString q = i18n("<qt>The handheld thinks that "
00161                     "the username is %1; "
00162                     "however, KPilot says you are %2."
00163                     "Which of these is the correct name?\n"
00164                     "If you click on Cancel, the sync will proceed, "
00165                     "but the usernames will not be changed.").
00166                     arg(pilotUserName).
00167                     arg(guiUserName);
00168 
00169                 int r = questionYesNoCancel(q,
00170                     i18n("User Mismatch"),
00171                     QString::null,
00172                     20,
00173                     i18n("Use KPilot Name"),
00174                     i18n("Use Handheld Name"));
00175                 switch (r)
00176                 {
00177                 case KMessageBox::Yes:
00178                     fHandle->getPilotUser().setUserName(
00179                         Pilot::toPilot(guiUserName));
00180                     pilotUserName=guiUserName;
00181                     break;
00182                 case KMessageBox::No:
00183                     KPilotSettings::setUserName(pilotUserName);
00184                     guiUserName=pilotUserName;
00185                     break;
00186                 case KMessageBox::Cancel:
00187                 default:
00188                     // TODO: cancel the sync... Or just don't change any user name?
00189                     break;
00190                 }
00191             }
00192         }
00193     }
00194 
00195 
00196 #ifdef DEBUG
00197     DEBUGKPILOT << fname
00198         << ": User name set to gui<"
00199         << guiUserName
00200         << "> hh<"
00201         << fHandle->getPilotUser().getUserName() << ">" << endl;
00202 #endif
00203 
00204     KPilotSettings::writeConfig();
00205 
00206     // Now we've established which user will be used,
00207     // fix the database location for local databases.
00208     //
00209     //
00210     QString pathName = KGlobal::dirs()->saveLocation("data",
00211         CSL1("kpilot/DBBackup/"));
00212     if (!guiUserName.isEmpty())
00213     {
00214         pathName.append(guiUserName);
00215         pathName.append(CSL1("/"));
00216     }
00217     PilotLocalDatabase::setDBPath(pathName);
00218 
00219     emit syncDone(this);
00220     return true;
00221 }
00222 
00223 class RestoreInfo
00224 {
00225 public:
00226     struct DBInfo DBInfo;
00227     QString path;
00228 } ;
00229 
00230 class RestoreAction::Private
00231 {
00232 public:
00233     QString fPreferRestoreDir; 
00235     QValueList<RestoreInfo> fDBList;
00236     QTimer fTimer;
00237     QValueList<RestoreInfo>::ConstIterator fDBIterator;
00238     int fDBIndex;
00239 };
00240 
00241 
00242 RestoreAction::RestoreAction(KPilotLink * p, QWidget * visible ) :
00243     SyncAction(p, visible, "restoreAction")
00244 {
00245     FUNCTIONSETUP;
00246 
00247     fP = new Private;
00248 }
00249 
00250 void RestoreAction::setDirectory( const QString &path )
00251 {
00252     fP->fPreferRestoreDir = path;
00253 }
00254 
00255 /* virtual */ bool RestoreAction::exec()
00256 {
00257     FUNCTIONSETUP;
00258 
00259     QString dirname;
00260     if (fP->fPreferRestoreDir.isEmpty())
00261     {
00262         dirname = PilotLocalDatabase::getDBPath();
00263     }
00264     else
00265     {
00266         dirname = fP->fPreferRestoreDir;
00267     }
00268 
00269 #ifdef DEBUG
00270     DEBUGKPILOT << fname << ": Restoring user " << dirname << endl;
00271 #endif
00272 
00273     QDir dir(dirname, QString::null, QDir::Name,
00274         QDir::Files | QDir::Readable | QDir::NoSymLinks);
00275 
00276     if (!dir.exists())
00277     {
00278         kdWarning() << k_funcinfo
00279             << ": Restore directory "
00280             << dirname << " does not exist." << endl;
00281         fActionStatus = Error;
00282         addSyncLogEntry(i18n("Restore directory does not exist.") +
00283             CSL1(" ") + i18n("Restore not performed."));
00284         return false;
00285     }
00286 
00287     dirname = dir.absPath();
00288     if (questionYesNo(i18n("<qt>Are you sure you want to completely "
00289                 "restore your Pilot from the backup directory "
00290                 "(<i>%1</i>)? This will erase any information "
00291                 "you currently have on your Pilot.</qt>").
00292             arg(dirname),
00293             i18n("Restore Pilot")) != KMessageBox::Yes)
00294     {
00295         emit logError(i18n("Restore <i>not</i> performed."));
00296 
00297         addSyncLogEntry(i18n("Canceled by user.") + CSL1(" ") +
00298             i18n("Restore not performed."));
00299 
00300         // You might call this an error, but that causes
00301         // a frightening message in the log .. and the
00302         // user already _knows_ the restore didn't happen.
00303         // So instead, act as if everything was ok.
00304         delayDone();
00305         return true;
00306     }
00307 
00308 
00309     emit logProgress(i18n("Restoring %1...").arg(QString::null),1);
00310 
00311     for (unsigned int i = 0; i < dir.count(); i++)
00312     {
00313         QString s;
00314         RestoreInfo info;
00315 
00316         s = dirname + QDir::separator() + dir[i];
00317 
00318         DEBUGKPILOT << fname
00319             << ": Adding " << s << " to restore list." << endl;
00320 
00321         if ( PilotLocalDatabase::infoFromFile( s, &info.DBInfo ) )
00322         {
00323             info.path = s;
00324             fP->fDBList.append(info);
00325         }
00326         else
00327         {
00328             kdWarning() << k_funcinfo
00329                 << ": Can't open " << s << endl;
00330             logMessage(i18n("File '%1' cannot be read.").arg(s));
00331         }
00332     }
00333 
00334     fP->fDBIndex = 0;
00335     fP->fDBIterator = fP->fDBList.begin();
00336     fActionStatus = InstallingFiles;
00337 
00338     QObject::connect(&(fP->fTimer), SIGNAL(timeout()),
00339         this, SLOT(installNextFile()));
00340 
00341     fP->fTimer.start(0, false);
00342     return true;
00343 }
00344 
00345 /* slot */ void RestoreAction::installNextFile()
00346 {
00347     FUNCTIONSETUP;
00348 
00349     Q_ASSERT(fActionStatus == InstallingFiles);
00350 
00351 
00352     if (fP->fDBIterator == fP->fDBList.end())
00353     {
00354         fP->fTimer.stop();
00355 
00356         fActionStatus = Done;
00357         addSyncLogEntry(i18n("OK."));
00358         delayDone();
00359         return;
00360     }
00361 
00362     const RestoreInfo dbi = *(fP->fDBIterator);
00363     ++(fP->fDBIterator);
00364     ++(fP->fDBIndex);
00365 
00366     DEBUGKPILOT << fname << ": Trying to install " << dbi.path << endl;
00367 
00368     if (openConduit() < 0)
00369     {
00370         kdWarning() << k_funcinfo
00371             << ": Restore apparently canceled." << endl;
00372         logMessage(i18n("Restore incomplete."));
00373         fActionStatus = Done;
00374         emit syncDone(this);
00375 
00376         return;
00377     }
00378 
00379     QFileInfo databaseInfo(dbi.path);
00380     addSyncLogEntry(databaseInfo.fileName());
00381     emit logProgress(i18n("Restoring %1...").arg(databaseInfo.fileName()),
00382         (100*fP->fDBIndex) / (fP->fDBList.count()+1)) ;
00383 
00384     if ( !deviceLink()->installFiles( dbi.path, false /* don't delete */ ) )
00385     {
00386         kdWarning() << k_funcinfo
00387             << ": Couldn't  restore " << dbi.path << endl;
00388         logError(i18n("Cannot restore file `%1'.")
00389             .arg(databaseInfo.fileName()));
00390     }
00391 }
00392 
00393 /* virtual */ QString RestoreAction::statusString() const
00394 {
00395     FUNCTIONSETUP;
00396     QString s;
00397 
00398     switch (status())
00399     {
00400     case InstallingFiles:
00401         s.append(CSL1("Installing Files ("));
00402         s.append(QString::number(fP->fDBIndex));
00403         s.append(CSL1(")"));
00404         break;
00405     case GettingFileInfo:
00406         s.append(CSL1("Getting File Info ("));
00407         s.append(QString::number(fP->fDBIndex));
00408         s.append(CSL1(")"));
00409         break;
00410     default:
00411         return SyncAction::statusString();
00412     }
00413 
00414     return s;
00415 }
00416 
00417 
KDE Home | KDE Accessibility Home | Description of Access Keys