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().setUserName(defaultUserName);
00111                 guiUserName=defaultUserName;
00112                 pilotUserName=defaultUserName;
00113             }
00114 
00115         }
00116         else
00117         {
00118             QString q = i18n("<qt>The handheld has a username set "
00119                 "(<i>%1</i>) but KPilot does not. Should "
00120                 "KPilot use this username in future?").
00121                 arg(pilotUserName);
00122 
00123             if (questionYesNo(q, i18n("User Unknown") /* ,"askUserSome" */ ) ==
00124                 KMessageBox::Yes)
00125             {
00126                 KPilotSettings::setUserName(pilotUserName);
00127                 guiUserName=pilotUserName;
00128             }
00129         }
00130     }
00131     else
00132     {
00133         if (pilotUserEmpty)
00134         {
00135             QString q = i18n("<qt>KPilot has a username set "
00136                 "(<i>%1</i>) but the handheld does not. "
00137                 "Should KPilot's username be set in the "
00138                 "handheld as well?").arg(guiUserName);
00139 
00140             if (questionYesNo(q, i18n("User Unknown") /* ,"askUserSome" */) ==
00141                 KMessageBox::Yes)
00142             {
00143 #ifdef DEBUG
00144                 DEBUGKPILOT << fname
00145                     << ": Setting user name in pilot to "
00146                     << guiUserName << endl;
00147 #endif
00148 
00149                 fHandle->getPilotUser().setUserName(guiUserName);
00150                 pilotUserName=guiUserName;
00151             }
00152         }
00153         else
00154         {
00155             if (guiUserName != pilotUserName)
00156             {
00157                 QString q = i18n("<qt>The handheld thinks that "
00158                     "the username is %1; "
00159                     "however, KPilot says you are %2."
00160                     "Which of these is the correct name?\n"
00161                     "If you click on Cancel, the sync will proceed, "
00162                     "but the usernames will not be changed.").
00163                     arg(pilotUserName).
00164                     arg(guiUserName);
00165 
00166                 int r = questionYesNoCancel(q,
00167                     i18n("User Mismatch"),
00168                     QString::null,
00169                     20,
00170                     i18n("Use KPilot Name"),
00171                     i18n("Use Handheld Name"));
00172                 switch (r)
00173                 {
00174                 case KMessageBox::Yes:
00175                     fHandle->getPilotUser().setUserName(guiUserName);
00176                     pilotUserName=guiUserName;
00177                     break;
00178                 case KMessageBox::No:
00179                     KPilotSettings::setUserName(pilotUserName);
00180                     guiUserName=pilotUserName;
00181                     break;
00182                 case KMessageBox::Cancel:
00183                 default:
00184                     // TODO: cancel the sync... Or just don't change any user name?
00185                     break;
00186                 }
00187             }
00188         }
00189     }
00190 
00191 
00192 #ifdef DEBUG
00193     DEBUGKPILOT << fname
00194         << ": User name set to gui<"
00195         << guiUserName
00196         << "> hh<"
00197         << fHandle->getPilotUser().getUserName() << ">" << endl;
00198 #endif
00199 
00200     KPilotSettings::writeConfig();
00201 
00202     // Now we've established which user will be used,
00203     // fix the database location for local databases.
00204     //
00205     //
00206     QString pathName = KGlobal::dirs()->saveLocation("data",
00207         CSL1("kpilot/DBBackup/"));
00208     if (!guiUserName.isEmpty())
00209     {
00210         pathName.append(guiUserName);
00211         pathName.append(CSL1("/"));
00212     }
00213     PilotLocalDatabase::setDBPath(pathName);
00214 
00215     emit syncDone(this);
00216     return true;
00217 }
00218 
00219 class RestoreInfo
00220 {
00221 public:
00222     struct DBInfo DBInfo;
00223     QString path;
00224 } ;
00225 
00226 class RestoreAction::Private
00227 {
00228 public:
00229     QString fPreferRestoreDir; 
00231     QValueList<RestoreInfo> fDBList;
00232     QTimer fTimer;
00233     QValueList<RestoreInfo>::ConstIterator fDBIterator;
00234     int fDBIndex;
00235 };
00236 
00237 
00238 RestoreAction::RestoreAction(KPilotLink * p, QWidget * visible ) :
00239     SyncAction(p, visible, "restoreAction")
00240 {
00241     FUNCTIONSETUP;
00242 
00243     fP = new Private;
00244 }
00245 
00246 void RestoreAction::setDirectory( const QString &path )
00247 {
00248     fP->fPreferRestoreDir = path;
00249 }
00250 
00251 /* virtual */ bool RestoreAction::exec()
00252 {
00253     FUNCTIONSETUP;
00254 
00255     QString dirname;
00256     if (fP->fPreferRestoreDir.isEmpty())
00257     {
00258         dirname = PilotLocalDatabase::getDBPath();
00259     }
00260     else
00261     {
00262         dirname = fP->fPreferRestoreDir;
00263     }
00264 
00265 #ifdef DEBUG
00266     DEBUGKPILOT << fname << ": Restoring user " << dirname << endl;
00267 #endif
00268 
00269     QDir dir(dirname, QString::null, QDir::Name,
00270         QDir::Files | QDir::Readable | QDir::NoSymLinks);
00271 
00272     if (!dir.exists())
00273     {
00274         kdWarning() << k_funcinfo
00275             << ": Restore directory "
00276             << dirname << " does not exist." << endl;
00277         fActionStatus = Error;
00278         addSyncLogEntry(i18n("Restore directory does not exist.") +
00279             CSL1(" ") + i18n("Restore not performed."));
00280         return false;
00281     }
00282 
00283     dirname = dir.absPath();
00284     if (questionYesNo(i18n("<qt>Are you sure you want to completely "
00285                 "restore your Pilot from the backup directory "
00286                 "(<i>%1</i>)? This will erase any information "
00287                 "you currently have on your Pilot.</qt>").
00288             arg(dirname),
00289             i18n("Restore Pilot")) != KMessageBox::Yes)
00290     {
00291         emit logError(i18n("Restore <i>not</i> performed."));
00292 
00293         addSyncLogEntry(i18n("Canceled by user.") + CSL1(" ") +
00294             i18n("Restore not performed."));
00295 
00296         // You might call this an error, but that causes
00297         // a frightening message in the log .. and the
00298         // user already _knows_ the restore didn't happen.
00299         // So instead, act as if everything was ok.
00300         delayDone();
00301         return true;
00302     }
00303 
00304 
00305     emit logProgress(i18n("Restoring %1...").arg(QString::null),1);
00306 
00307     for (unsigned int i = 0; i < dir.count(); i++)
00308     {
00309         QString s;
00310         RestoreInfo info;
00311 
00312         s = dirname + QDir::separator() + dir[i];
00313 
00314         DEBUGKPILOT << fname
00315             << ": Adding " << s << " to restore list." << endl;
00316 
00317         if ( PilotLocalDatabase::infoFromFile( s, &info.DBInfo ) )
00318         {
00319             info.path = s;
00320             fP->fDBList.append(info);
00321         }
00322         else
00323         {
00324             kdWarning() << k_funcinfo
00325                 << ": Can't open " << s << endl;
00326             logMessage(i18n("File '%1' cannot be read.").arg(s));
00327         }
00328     }
00329 
00330     fP->fDBIndex = 0;
00331     fP->fDBIterator = fP->fDBList.begin();
00332     fActionStatus = InstallingFiles;
00333 
00334     QObject::connect(&(fP->fTimer), SIGNAL(timeout()),
00335         this, SLOT(installNextFile()));
00336 
00337     fP->fTimer.start(0, false);
00338     return true;
00339 }
00340 
00341 /* slot */ void RestoreAction::installNextFile()
00342 {
00343     FUNCTIONSETUP;
00344 
00345     Q_ASSERT(fActionStatus == InstallingFiles);
00346 
00347 
00348     if (fP->fDBIterator == fP->fDBList.end())
00349     {
00350         fP->fTimer.stop();
00351 
00352         fActionStatus = Done;
00353         addSyncLogEntry(i18n("OK."));
00354         delayDone();
00355         return;
00356     }
00357 
00358     const RestoreInfo dbi = *(fP->fDBIterator);
00359     ++(fP->fDBIterator);
00360     ++(fP->fDBIndex);
00361 
00362     DEBUGKPILOT << fname << ": Trying to install " << dbi.path << endl;
00363 
00364     if (openConduit() < 0)
00365     {
00366         kdWarning() << k_funcinfo
00367             << ": Restore apparently canceled." << endl;
00368         logMessage(i18n("Restore incomplete."));
00369         fActionStatus = Done;
00370         emit syncDone(this);
00371 
00372         return;
00373     }
00374 
00375     QFileInfo databaseInfo(dbi.path);
00376     addSyncLogEntry(databaseInfo.fileName());
00377     emit logProgress(i18n("Restoring %1...").arg(databaseInfo.fileName()),
00378         (100*fP->fDBIndex) / (fP->fDBList.count()+1)) ;
00379 
00380     if ( !deviceLink()->installFiles( dbi.path, false /* don't delete */ ) )
00381     {
00382         kdWarning() << k_funcinfo
00383             << ": Couldn't  restore " << dbi.path << endl;
00384         logError(i18n("Cannot restore file `%1'.")
00385             .arg(databaseInfo.fileName()));
00386     }
00387 }
00388 
00389 /* virtual */ QString RestoreAction::statusString() const
00390 {
00391     FUNCTIONSETUP;
00392     QString s;
00393 
00394     switch (status())
00395     {
00396     case InstallingFiles:
00397         s.append(CSL1("Installing Files ("));
00398         s.append(QString::number(fP->fDBIndex));
00399         s.append(CSL1(")"));
00400         break;
00401     case GettingFileInfo:
00402         s.append(CSL1("Getting File Info ("));
00403         s.append(QString::number(fP->fDBIndex));
00404         s.append(CSL1(")"));
00405         break;
00406     default:
00407         return SyncAction::statusString();
00408     }
00409 
00410     return s;
00411 }
00412 
00413 
KDE Home | KDE Accessibility Home | Description of Access Keys