kpilot/kpilot

syncStack.cc

00001 /* KPilot
00002 **
00003 ** Copyright (C) 1998-2001 by Dan Pilone
00004 ** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005 **
00006 ** This defines the "ActionQueue", which is the pile of actions
00007 ** that will occur during a HotSync.
00008 */
00009 
00010 /*
00011 ** This program is free software; you can redistribute it and/or modify
00012 ** it under the terms of the GNU General Public License as published by
00013 ** the Free Software Foundation; either version 2 of the License, or
00014 ** (at your option) any later version.
00015 **
00016 ** This program is distributed in the hope that it will be useful,
00017 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019 ** GNU General Public License for more details.
00020 **
00021 ** You should have received a copy of the GNU General Public License
00022 ** along with this program in a file called COPYING; if not, write to
00023 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00024 ** MA 02110-1301, USA.
00025 */
00026 
00027 /*
00028 ** Bug reports and questions can be sent to kde-pim@kde.org
00029 */
00030 #include "options.h"
00031 
00032 #include <unistd.h>
00033 
00034 #include <qtimer.h>
00035 #include <qfile.h>
00036 #include <qdir.h>
00037 
00038 #include <kservice.h>
00039 #include <kservicetype.h>
00040 #include <kuserprofile.h>
00041 #include <klibloader.h>
00042 #include <ksavefile.h>
00043 
00044 #include "pilotUser.h"
00045 #include "hotSync.h"
00046 #include "interactiveSync.h"
00047 #include "fileInstaller.h"
00048 #include "kpilotSettings.h"
00049 #include "pilotRecord.h"
00050 
00051 #include "syncStack.moc"
00052 
00053 
00054 
00055 WelcomeAction::WelcomeAction(KPilotLink *p) :
00056     SyncAction(p,"welcomeAction")
00057 {
00058     FUNCTIONSETUP;
00059 }
00060 
00061 /* virtual */ bool WelcomeAction::exec()
00062 {
00063     FUNCTIONSETUP;
00064 
00065     addSyncLogEntry(i18n("KPilot %1 HotSync starting...\n")
00066         .arg(QString::fromLatin1(KPILOT_VERSION)));
00067     emit logMessage( i18n("Using encoding %1 on the handheld.").arg(Pilot::codecName()) );
00068     emit syncDone(this);
00069     return true;
00070 }
00071 
00072 SorryAction::SorryAction(KPilotLink *p, const QString &s) :
00073     SyncAction(p,"sorryAction"),
00074     fMessage(s)
00075 {
00076     if (fMessage.isEmpty())
00077     {
00078         fMessage = i18n("KPilot is busy and cannot process the "
00079             "HotSync right now.");
00080     }
00081 }
00082 
00083 bool SorryAction::exec()
00084 {
00085     FUNCTIONSETUP;
00086 
00087     addSyncLogEntry(fMessage);
00088     return delayDone();
00089 }
00090 
00091 LocalBackupAction::LocalBackupAction(KPilotLink *p, const QString &d) :
00092     SyncAction(p,"LocalBackupAction"),
00093     fDir(d)
00094 {
00095 }
00096 
00097 bool LocalBackupAction::exec()
00098 {
00099     FUNCTIONSETUP;
00100 
00101     startTickle();
00102 
00103     QString dirname = fDir +
00104         Pilot::fromPilot(fHandle->getPilotUser().getUserName()) +
00105         CSL1("/");
00106     QDir dir(dirname,QString::null,QDir::Unsorted,QDir::Files);
00107 
00108     if (!dir.exists())
00109     {
00110         emit logMessage( i18n("Cannot create local backup.") );
00111         return false;
00112     }
00113 
00114     logMessage( i18n("Creating local backup of databases in %1.").arg(dirname) );
00115     addSyncLogEntry( i18n("Creating local backup ..") );
00116     qApp->processEvents();
00117 
00118     QStringList files = dir.entryList();
00119 
00120     for (QStringList::Iterator i = files.begin() ;
00121         i != files.end();
00122         ++i)
00123     {
00124         KSaveFile::backupFile(dirname + (*i));
00125     }
00126 
00127     stopTickle();
00128 
00129     return delayDone();
00130 }
00131 
00132 
00133 ConduitProxy::ConduitProxy(KPilotLink *p,
00134     const QString &name,
00135     const SyncAction::SyncMode &m) :
00136     ConduitAction(p,name.latin1(),m.list()),
00137     fDesktopName(name)
00138 {
00139     FUNCTIONSETUP;
00140 }
00141 
00142 /* virtual */ bool ConduitProxy::exec()
00143 {
00144     FUNCTIONSETUP;
00145 
00146     // query that service
00147     KSharedPtr < KService > o = KService::serviceByDesktopName(fDesktopName);
00148     if (!o)
00149     {
00150         kdWarning() << k_funcinfo
00151             << ": Can't find desktop file for conduit "
00152             << fDesktopName
00153             << endl;
00154         addSyncLogEntry(i18n("Could not find conduit %1.").arg(fDesktopName));
00155         emit syncDone(this);
00156         return true;
00157     }
00158 
00159 
00160     // load the lib
00161     fLibraryName = o->library();
00162 #ifdef DEBUG
00163     DEBUGKPILOT << fname
00164         << ": Loading desktop "
00165         << fDesktopName
00166         << " with lib "
00167         << fLibraryName
00168         << endl;
00169 #endif
00170 
00171     KLibrary *library = KLibLoader::self()->library(
00172         QFile::encodeName(fLibraryName));
00173     if (!library)
00174     {
00175         kdWarning() << k_funcinfo
00176             << ": Can't load library "
00177             << fLibraryName
00178             << " - "
00179             << KLibLoader::self()->lastErrorMessage()
00180             << endl;
00181         addSyncLogEntry(i18n("Could not load conduit %1.").arg(fDesktopName));
00182         emit syncDone(this);
00183         return true;
00184     }
00185 
00186     unsigned long version = PluginUtility::pluginVersion(library);
00187     if ( Pilot::PLUGIN_API != version )
00188     {
00189         kdWarning() << k_funcinfo
00190             << ": Library "
00191             << fLibraryName
00192             << " has version "
00193             << version
00194             << endl;
00195         addSyncLogEntry(i18n("Conduit %1 has wrong version (%2).").arg(fDesktopName).arg(version));
00196         emit syncDone(this);
00197         return true;
00198     }
00199 
00200     KLibFactory *factory = library->factory();
00201     if (!factory)
00202     {
00203         kdWarning() << k_funcinfo
00204             << ": Can't find factory in library "
00205             << fLibraryName
00206             << endl;
00207         addSyncLogEntry(i18n("Could not initialize conduit %1.").arg(fDesktopName));
00208         emit syncDone(this);
00209         return true;
00210     }
00211 
00212     QStringList l = syncMode().list();
00213 
00214 #ifdef DEBUG
00215     DEBUGKPILOT << fname << ": Flags: " << syncMode().name() << endl;
00216 #endif
00217 
00218     QObject *object = factory->create(fHandle,name(),"SyncAction",l);
00219 
00220     if (!object)
00221     {
00222         kdWarning() << k_funcinfo
00223             << ": Can't create SyncAction."
00224             << endl;
00225         addSyncLogEntry(i18n("Could not create conduit %1.").arg(fDesktopName));
00226         emit syncDone(this);
00227         return true;
00228     }
00229 
00230     fConduit = dynamic_cast<ConduitAction *>(object);
00231 
00232     if (!fConduit)
00233     {
00234         kdWarning() << k_funcinfo
00235             << ": Can't cast to ConduitAction."
00236             << endl;
00237         addSyncLogEntry(i18n("Could not create conduit %1.").arg(fDesktopName));
00238         emit syncDone(this);
00239         return true;
00240     }
00241 
00242     addSyncLogEntry(i18n("[Conduit %1]").arg(fDesktopName));
00243 
00244     // Handle the syncDone signal properly & unload the conduit.
00245     QObject::connect(fConduit,SIGNAL(syncDone(SyncAction *)),
00246         this,SLOT(execDone(SyncAction *)));
00247     // Proxy all the log and error messages.
00248     QObject::connect(fConduit,SIGNAL(logMessage(const QString &)),
00249         this,SIGNAL(logMessage(const QString &)));
00250     QObject::connect(fConduit,SIGNAL(logError(const QString &)),
00251         this,SIGNAL(logError(const QString &)));
00252     QObject::connect(fConduit,SIGNAL(logProgress(const QString &,int)),
00253         this,SIGNAL(logProgress(const QString &,int)));
00254 
00255     QTimer::singleShot(0,fConduit,SLOT(execConduit()));
00256     return true;
00257 }
00258 
00259 void ConduitProxy::execDone(SyncAction *p)
00260 {
00261     FUNCTIONSETUP;
00262 
00263     if (p!=fConduit)
00264     {
00265         kdError() << k_funcinfo
00266             << ": Unknown conduit @"
00267             << (long) p
00268             << " finished."
00269             << endl;
00270         emit syncDone(this);
00271         return;
00272     }
00273 
00274     delete p;
00275     addSyncLogEntry(CSL1("\n"),false); // Put bits of the conduit logs on separate lines
00276     emit syncDone(this);
00277 }
00278 
00279 
00280 ActionQueue::ActionQueue(KPilotLink *d) :
00281     SyncAction(d,"ActionQueue"),
00282     fReady(false)
00283     // The string lists have default constructors
00284 {
00285     FUNCTIONSETUP;
00286 }
00287 
00288 ActionQueue::~ActionQueue()
00289 {
00290     FUNCTIONSETUP;
00291 }
00292 
00293 
00294 void ActionQueue::queueInit( ActionQueue::InitFlags checkUser)
00295 {
00296     FUNCTIONSETUP;
00297 
00298     addAction(new WelcomeAction(fHandle));
00299 
00300     if ( ActionQueue::queueCheckUser == checkUser)
00301     {
00302         addAction(new CheckUser(fHandle));
00303     }
00304 }
00305 
00306 void ActionQueue::queueConduits(const QStringList &l,const SyncAction::SyncMode &m, bool /*local*/)
00307 {
00308     FUNCTIONSETUP;
00309 
00310     // Add conduits here ...
00311     //
00312     //
00313     for (QStringList::ConstIterator it = l.begin();
00314         it != l.end();
00315         ++it)
00316     {
00317         if ((*it).startsWith(CSL1("internal_")))
00318         {
00319 #ifdef DEBUG
00320             DEBUGKPILOT << fname <<
00321                 ": Ignoring conduit " << *it << endl;
00322 #endif
00323             continue;
00324         }
00325 
00326 #ifdef DEBUG
00327         DEBUGKPILOT << fname
00328             << ": Creating proxy with mode=" << m.name() << endl;
00329 #endif
00330         ConduitProxy *cp = new ConduitProxy(fHandle,*it,m);
00331         addAction(cp);
00332     }
00333 }
00334 
00335 void ActionQueue::queueInstaller(const QString &dir)
00336 {
00337     addAction(new FileInstallAction(fHandle,dir));
00338 }
00339 
00340 void ActionQueue::queueCleanup()
00341 {
00342     addAction(new CleanupAction(fHandle));
00343 }
00344 
00345 bool ActionQueue::exec()
00346 {
00347     actionCompleted(0L);
00348     return true;
00349 }
00350 
00351 void ActionQueue::actionCompleted(SyncAction *b)
00352 {
00353     FUNCTIONSETUP;
00354 
00355     if (b)
00356     {
00357 #ifdef DEBUG
00358         DEBUGKPILOT << fname
00359             << ": Completed action "
00360             << b->name()
00361             << endl;
00362 #endif
00363         delete b;
00364     }
00365 
00366     if (isEmpty())
00367     {
00368         delayDone();
00369         return;
00370     }
00371     if ( deviceLink() && (!deviceLink()->tickle()) )
00372     {
00373         emit logError(i18n("The connection to the handheld "
00374             "was lost. Synchronization cannot continue."));
00375         SyncAction *del = 0L;
00376         while ( (del = nextAction()) )
00377         {
00378             delete del;
00379         }
00380         delayDone();
00381         return;
00382     }
00383 
00384     SyncAction *a = nextAction();
00385 
00386     if (!a)
00387     {
00388         kdWarning() << k_funcinfo
00389             << ": NULL action on stack."
00390             << endl;
00391         return;
00392     }
00393 
00394 #ifdef DEBUG
00395     DEBUGKPILOT << fname
00396         << ": Will run action "
00397         << a->name()
00398         << endl;
00399 #endif
00400 
00401     QObject::connect(a, SIGNAL(logMessage(const QString &)),
00402         this, SIGNAL(logMessage(const QString &)));
00403     QObject::connect(a, SIGNAL(logError(const QString &)),
00404         this, SIGNAL(logMessage(const QString &)));
00405     QObject::connect(a, SIGNAL(logProgress(const QString &, int)),
00406         this, SIGNAL(logProgress(const QString &, int)));
00407     QObject::connect(a, SIGNAL(syncDone(SyncAction *)),
00408         this, SLOT(actionCompleted(SyncAction *)));
00409 
00410     QTimer::singleShot(0,a,SLOT(execConduit()));
00411 }
00412 
KDE Home | KDE Accessibility Home | Description of Access Keys