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 static const char *syncStack_id = "$Id: syncStack.cc 449694 2005-08-16 13:07:41Z adridg $";
00033 
00034 #include <unistd.h>
00035 
00036 #include <qtimer.h>
00037 #include <qfile.h>
00038 #include <qdir.h>
00039 #include <qtextcodec.h>
00040 
00041 #include <kservice.h>
00042 #include <kservicetype.h>
00043 #include <kuserprofile.h>
00044 #include <klibloader.h>
00045 #include <ksavefile.h>
00046 
00047 #include "pilotUser.h"
00048 #include "hotSync.h"
00049 #include "interactiveSync.h"
00050 #include "fileInstaller.h"
00051 #include "kpilotSettings.h"
00052 #include "pilotAppCategory.h"
00053 
00054 #include "syncStack.moc"
00055 
00056 
00057 
00058 WelcomeAction::WelcomeAction(KPilotDeviceLink *p) :
00059     SyncAction(p,"welcomeAction")
00060 {
00061     FUNCTIONSETUP;
00062 
00063     (void) syncStack_id;
00064 }
00065 
00066 /* virtual */ bool WelcomeAction::exec()
00067 {
00068     FUNCTIONSETUP;
00069 
00070     addSyncLogEntry(i18n("KPilot %1 HotSync starting...\n")
00071         .arg(QString::fromLatin1(KPILOT_VERSION)));
00072     emit logMessage( i18n("Using encoding %1 on the handheld.").arg(PilotAppCategory::codecName()) );
00073     emit syncDone(this);
00074     return true;
00075 }
00076 
00077 SorryAction::SorryAction(KPilotDeviceLink *p, const QString &s) :
00078     SyncAction(p,"sorryAction"),
00079     fMessage(s)
00080 {
00081     if (fMessage.isEmpty())
00082     {
00083         fMessage = i18n("KPilot is busy and cannot process the "
00084             "HotSync right now.");
00085     }
00086 }
00087 
00088 bool SorryAction::exec()
00089 {
00090     FUNCTIONSETUP;
00091 
00092     addSyncLogEntry(fMessage);
00093     return delayDone();
00094 }
00095 
00096 LocalBackupAction::LocalBackupAction(KPilotDeviceLink *p, const QString &d) :
00097     SyncAction(p,"LocalBackupAction"),
00098     fDir(d)
00099 {
00100 }
00101 
00102 bool LocalBackupAction::exec()
00103 {
00104     FUNCTIONSETUP;
00105 
00106     startTickle();
00107 
00108     QString dirname = fDir +
00109         PilotAppCategory::codec()->toUnicode(fHandle->getPilotUser()->getUserName()) +
00110         CSL1("/");
00111     QDir dir(dirname,QString::null,QDir::Unsorted,QDir::Files);
00112 
00113     if (!dir.exists())
00114     {
00115         emit logMessage( i18n("Cannot create local backup.") );
00116         return false;
00117     }
00118 
00119     logMessage( i18n("Creating local backup of databases in %1.").arg(dirname) );
00120     addSyncLogEntry( i18n("Creating local backup ..") );
00121     qApp->processEvents();
00122 
00123     QStringList files = dir.entryList();
00124 
00125     for (QStringList::Iterator i = files.begin() ;
00126         i != files.end();
00127         ++i)
00128     {
00129         KSaveFile::backupFile(dirname + (*i));
00130     }
00131 
00132     stopTickle();
00133 
00134     return delayDone();
00135 }
00136 
00137 
00138 ConduitProxy::ConduitProxy(KPilotDeviceLink *p,
00139     const QString &name,
00140     const SyncAction::SyncMode &m) :
00141     ConduitAction(p,name.latin1(),m.list()),
00142     fDesktopName(name)
00143 {
00144     FUNCTIONSETUP;
00145 }
00146 
00147 /* virtual */ bool ConduitProxy::exec()
00148 {
00149     FUNCTIONSETUP;
00150 
00151     // query that service
00152     KSharedPtr < KService > o = KService::serviceByDesktopName(fDesktopName);
00153     if (!o)
00154     {
00155         kdWarning() << k_funcinfo
00156             << ": Can't find desktop file for conduit "
00157             << fDesktopName
00158             << endl;
00159         addSyncLogEntry(i18n("Could not find conduit %1.").arg(fDesktopName));
00160         emit syncDone(this);
00161         return true;
00162     }
00163 
00164 
00165     // load the lib
00166     fLibraryName = o->library();
00167 #ifdef DEBUG
00168     DEBUGKPILOT << fname
00169         << ": Loading desktop "
00170         << fDesktopName
00171         << " with lib "
00172         << fLibraryName
00173         << endl;
00174 #endif
00175 
00176     KLibFactory *factory = KLibLoader::self()->factory(
00177         QFile::encodeName(fLibraryName));
00178     if (!factory)
00179     {
00180         kdWarning() << k_funcinfo
00181             << ": Can't load library "
00182             << fLibraryName
00183             << endl;
00184         addSyncLogEntry(i18n("Could not load conduit %1.").arg(fDesktopName));
00185         emit syncDone(this);
00186         return true;
00187     }
00188 
00189     QStringList l = syncMode().list();
00190 
00191 #ifdef DEBUG
00192     DEBUGDAEMON << fname << ": Flags: " << syncMode().name() << endl;
00193 #endif
00194 
00195     QObject *object = factory->create(fHandle,name(),"SyncAction",l);
00196 
00197     if (!object)
00198     {
00199         kdWarning() << k_funcinfo
00200             << ": Can't create SyncAction."
00201             << endl;
00202         addSyncLogEntry(i18n("Could not create conduit %1.").arg(fDesktopName));
00203         emit syncDone(this);
00204         return true;
00205     }
00206 
00207     fConduit = dynamic_cast<ConduitAction *>(object);
00208 
00209     if (!fConduit)
00210     {
00211         kdWarning() << k_funcinfo
00212             << ": Can't cast to ConduitAction."
00213             << endl;
00214         addSyncLogEntry(i18n("Could not create conduit %1.").arg(fDesktopName));
00215         emit syncDone(this);
00216         return true;
00217     }
00218 
00219     addSyncLogEntry(i18n("[Conduit %1]").arg(fDesktopName));
00220 
00221     // Handle the syncDone signal properly & unload the conduit.
00222     QObject::connect(fConduit,SIGNAL(syncDone(SyncAction *)),
00223         this,SLOT(execDone(SyncAction *)));
00224     // Proxy all the log and error messages.
00225     QObject::connect(fConduit,SIGNAL(logMessage(const QString &)),
00226         this,SIGNAL(logMessage(const QString &)));
00227     QObject::connect(fConduit,SIGNAL(logError(const QString &)),
00228         this,SIGNAL(logError(const QString &)));
00229     QObject::connect(fConduit,SIGNAL(logProgress(const QString &,int)),
00230         this,SIGNAL(logProgress(const QString &,int)));
00231 
00232     QTimer::singleShot(0,fConduit,SLOT(execConduit()));
00233     return true;
00234 }
00235 
00236 void ConduitProxy::execDone(SyncAction *p)
00237 {
00238     FUNCTIONSETUP;
00239 
00240     if (p!=fConduit)
00241     {
00242         kdError() << k_funcinfo
00243             << ": Unknown conduit @"
00244             << (long) p
00245             << " finished."
00246             << endl;
00247         emit syncDone(this);
00248         return;
00249     }
00250 
00251     delete p;
00252     addSyncLogEntry(CSL1("\n"),false); // Put bits of the conduit logs on separate lines
00253     emit syncDone(this);
00254 }
00255 
00256 
00257 ActionQueue::ActionQueue(KPilotDeviceLink *d) :
00258     SyncAction(d,"ActionQueue"),
00259     fReady(false)
00260     // The string lists have default constructors
00261 {
00262     FUNCTIONSETUP;
00263 }
00264 
00265 ActionQueue::~ActionQueue()
00266 {
00267     FUNCTIONSETUP;
00268 }
00269 
00270 
00271 void ActionQueue::queueInit(bool checkUser)
00272 {
00273     FUNCTIONSETUP;
00274 
00275     addAction(new WelcomeAction(fHandle));
00276 
00277     if (checkUser)
00278     {
00279         addAction(new CheckUser(fHandle));
00280     }
00281 }
00282 
00283 void ActionQueue::queueConduits(const QStringList &l,const SyncAction::SyncMode &m, bool /*local*/)
00284 {
00285     FUNCTIONSETUP;
00286 
00287     // Add conduits here ...
00288     //
00289     //
00290     for (QStringList::ConstIterator it = l.begin();
00291         it != l.end();
00292         ++it)
00293     {
00294         if ((*it).startsWith(CSL1("internal_")))
00295         {
00296 #ifdef DEBUG
00297             DEBUGDAEMON << fname <<
00298                 ": Ignoring conduit " << *it << endl;
00299 #endif
00300             continue;
00301         }
00302 
00303 #ifdef DEBUG
00304         DEBUGDAEMON << fname
00305             << ": Creating proxy with mode=" << m.name() << endl;
00306 #endif
00307         ConduitProxy *cp = new ConduitProxy(fHandle,*it,m);
00308         addAction(cp);
00309     }
00310 }
00311 
00312 void ActionQueue::queueInstaller(const QString &dir)
00313 {
00314     addAction(new FileInstallAction(fHandle,dir));
00315 }
00316 
00317 void ActionQueue::queueCleanup()
00318 {
00319     addAction(new CleanupAction(fHandle));
00320 }
00321 
00322 bool ActionQueue::exec()
00323 {
00324     actionCompleted(0L);
00325     return true;
00326 }
00327 
00328 void ActionQueue::actionCompleted(SyncAction *b)
00329 {
00330     FUNCTIONSETUP;
00331 
00332     if (b)
00333     {
00334 #ifdef DEBUG
00335         DEBUGDAEMON << fname
00336             << ": Completed action "
00337             << b->name()
00338             << endl;
00339 #endif
00340         delete b;
00341     }
00342 
00343     if (isEmpty())
00344     {
00345         delayDone();
00346         return;
00347     }
00348     if ( deviceLink() && (!deviceLink()->tickle()) )
00349     {
00350         emit logError(i18n("The connection to the handheld "
00351             "was lost. Synchronization cannot continue."));
00352         SyncAction *del = 0L;
00353         while ( (del = nextAction()) )
00354         {
00355             delete del;
00356         }
00357         delayDone();
00358         return;
00359     }
00360 
00361     SyncAction *a = nextAction();
00362 
00363     if (!a)
00364     {
00365         kdWarning() << k_funcinfo
00366             << ": NULL action on stack."
00367             << endl;
00368         return;
00369     }
00370 
00371 #ifdef DEBUG
00372     DEBUGDAEMON << fname
00373         << ": Will run action "
00374         << a->name()
00375         << endl;
00376 #endif
00377 
00378     QObject::connect(a, SIGNAL(logMessage(const QString &)),
00379         this, SIGNAL(logMessage(const QString &)));
00380     QObject::connect(a, SIGNAL(logError(const QString &)),
00381         this, SIGNAL(logMessage(const QString &)));
00382     QObject::connect(a, SIGNAL(logProgress(const QString &, int)),
00383         this, SIGNAL(logProgress(const QString &, int)));
00384     QObject::connect(a, SIGNAL(syncDone(SyncAction *)),
00385         this, SLOT(actionCompleted(SyncAction *)));
00386 
00387     QTimer::singleShot(0,a,SLOT(execConduit()));
00388 }
00389 
KDE Home | KDE Accessibility Home | Description of Access Keys