kpilot Library API Documentation

pilotDaemon.cc

00001 /* pilotDaemon.cc           KPilot
00002 **
00003 ** Copyright (C) 1998-2001 by Dan Pilone
00004 **
00005 ** This is the KPilot Daemon, which does the actual communication with
00006 ** the Pilot and with the conduits.
00007 */
00008 
00009 /*
00010 ** This program is free software; you can redistribute it and/or modify
00011 ** it under the terms of the GNU General Public License as published by
00012 ** the Free Software Foundation; either version 2 of the License, or
00013 ** (at your option) any later version.
00014 **
00015 ** This program is distributed in the hope that it will be useful,
00016 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00018 ** GNU General Public License for more details.
00019 **
00020 ** You should have received a copy of the GNU General Public License
00021 ** along with this program in a file called COPYING; if not, write to
00022 ** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00023 ** MA 02111-1307, USA.
00024 */
00025 
00026 /*
00027 ** Bug reports and questions can be sent to kde-pim@kde.org
00028 */
00029 static const char *pilotdaemon_id =
00030     "$Id: pilotDaemon.cc,v 1.94 2003/10/13 21:33:27 goossens Exp $";
00031 
00032 // Heck yeah.
00033 #define ENABLE_KROUPWARE
00034 
00035 #ifndef _KPILOT_OPTIONS_H
00036 #include "options.h"
00037 #endif
00038 
00039 #include <time.h>
00040 
00041 #ifdef TIME_WITH_SYS_TIME
00042 #include <sys/time.h>
00043 #endif
00044 
00045 #include <sys/types.h>
00046 #include <sys/stat.h>
00047 #include <dirent.h>
00048 #include <fcntl.h>
00049 #include <unistd.h>
00050 #include <stdio.h>
00051 #include <stdlib.h>
00052 #include <signal.h>
00053 #include <errno.h>
00054 
00055 #include <qdir.h>
00056 #include <qptrlist.h>
00057 #include <qcursor.h>
00058 #include <qptrstack.h>
00059 #include <qtimer.h>
00060 #include <qtooltip.h>
00061 
00062 #include <kuniqueapplication.h>
00063 #include <kaboutdata.h>
00064 #include <kaboutapplication.h>
00065 #include <kcmdlineargs.h>
00066 #include <kwin.h>
00067 #include <ksimpleconfig.h>
00068 #include <kurl.h>
00069 #include <ksock.h>
00070 #include <kmessagebox.h>
00071 #include <kstandarddirs.h>
00072 #include <kpopupmenu.h>
00073 #include <kiconloader.h>
00074 #include <kio/netaccess.h>
00075 #include <kdebug.h>
00076 #include <ktempfile.h>
00077 #include <kprocess.h>
00078 #include <dcopclient.h>
00079 #include <kurldrag.h>
00080 
00081 #include "pilotAppCategory.h"
00082 
00083 #include "fileInstaller.h"
00084 #include "kpilotConfig.h"
00085 #include "pilotUser.h"
00086 
00087 #include "hotSync.h"
00088 #include "interactiveSync.h"
00089 #include "syncStack.h"
00090 #include "internalEditorAction.h"
00091 
00092 #ifdef ENABLE_KROUPWARE
00093 #include "kroupware.h"
00094 #endif
00095 
00096 #include "kpilotDCOP_stub.h"
00097 #include "kpilotDCOP.h"
00098 #include "logWidgetDCOP_stub.h"
00099 
00100 #include "pilotDaemon.moc"
00101 
00102 
00103 PilotDaemonTray::PilotDaemonTray(PilotDaemon * p) :
00104     KSystemTray(0, "pilotDaemon"),
00105     daemon(p),
00106     kap(0L)
00107 {
00108     FUNCTIONSETUP;
00109     setupWidget();
00110     setAcceptDrops(true);
00111 
00112 
00113     /* NOTREACHED */
00114     (void) pilotdaemon_id;
00115 }
00116 
00117 /* virtual */ void PilotDaemonTray::dragEnterEvent(QDragEnterEvent * e)
00118 {
00119     FUNCTIONSETUP;
00120     e->accept(KURLDrag::canDecode(e));
00121 }
00122 
00123 /* virtual */ void PilotDaemonTray::dropEvent(QDropEvent * e)
00124 {
00125     FUNCTIONSETUP;
00126 
00127     KURL::List list;
00128 
00129     KURLDrag::decode(e, list);
00130 
00131     QStringList files;
00132     for(KURL::List::ConstIterator it = list.begin(); it != list.end(); ++it)
00133     {
00134        if ((*it).isLocalFile())
00135           files << (*it).path();
00136     }
00137 
00138     daemon->addInstallFiles(files);
00139 }
00140 
00141 /* virtual */ void PilotDaemonTray::mousePressEvent(QMouseEvent * e)
00142 {
00143     FUNCTIONSETUP;
00144 
00145     switch (e->button())
00146     {
00147         case RightButton:
00148             {
00149                 KPopupMenu *menu = contextMenu();
00150                 contextMenuAboutToShow(menu);
00151                 menu->popup(e->globalPos());
00152             }
00153             break;
00154         case LeftButton:
00155             if (daemon) daemon->slotRunKPilot();
00156             break;
00157         default:
00158             KSystemTray::mousePressEvent(e);
00159     }
00160 }
00161 
00162 /* virtual */ void PilotDaemonTray::closeEvent(QCloseEvent *)
00163 {
00164     FUNCTIONSETUP;
00165     daemon->quitNow();
00166 }
00167 
00168 void PilotDaemonTray::setupWidget()
00169 {
00170     FUNCTIONSETUP;
00171 
00172     KGlobal::iconLoader()->addAppDir(CSL1("kpilot"));
00173     icon = SmallIcon(CSL1("hotsync"));
00174     busyicon = SmallIcon(CSL1("busysync"));
00175 
00176     slotShowBusy();
00177     QTimer::singleShot(2000,this,SLOT(slotShowNormal()));
00178 
00179     KPopupMenu *menu = contextMenu();
00180 
00181     menu->insertItem(i18n("&About"), this, SLOT(slotShowAbout()));
00182     menuKPilotItem = menu->insertItem(i18n("Start &KPilot"), daemon,
00183         SLOT(slotRunKPilot()));
00184 
00185     menuConfigureConduitsItem = menu->insertItem(i18n("&Configure Conduits..."),
00186         daemon, SLOT(slotRunConduitConfig()));
00187 
00188 #ifdef DEBUG
00189     DEBUGDAEMON << fname << ": Finished getting icons" << endl;
00190 #endif
00191 }
00192 
00193 void PilotDaemonTray::slotShowAbout()
00194 {
00195     FUNCTIONSETUP;
00196 
00197     if (!kap)
00198     {
00199         kap = new KAboutApplication(0, "kpdab", false);
00200     }
00201 
00202     kap->show();
00203 }
00204 
00205 
00206 void PilotDaemonTray::enableRunKPilot(bool b)
00207 {
00208     FUNCTIONSETUP;
00209     contextMenu()->setItemEnabled(menuKPilotItem, b);
00210     contextMenu()->setItemEnabled(menuConfigureConduitsItem, b);
00211 }
00212 
00213 
00214 void PilotDaemonTray::changeIcon(IconShape i)
00215 {
00216     FUNCTIONSETUP;
00217 
00218     switch (i)
00219     {
00220     case Normal:
00221         if (icon.isNull())
00222         {
00223             kdWarning() << k_funcinfo
00224                 << ": Regular icon is NULL!" << endl;
00225         }
00226         setPixmap(icon);
00227         break;
00228     case Busy:
00229         if (busyicon.isNull())
00230         {
00231             kdWarning() << k_funcinfo
00232                 << ": Busy icon is NULL!" << endl;
00233         }
00234         setPixmap(busyicon);
00235         break;
00236     default:
00237         kdWarning() << k_funcinfo
00238             << ": Bad icon number " << (int) i << endl;
00239     }
00240 }
00241 
00242 void PilotDaemonTray::slotShowNormal()
00243 {
00244     FUNCTIONSETUP;
00245     changeIcon(Normal);
00246 }
00247 
00248 void PilotDaemonTray::slotShowBusy()
00249 {
00250     FUNCTIONSETUP;
00251     changeIcon(Busy);
00252 }
00253 
00254 
00255 
00256 PilotDaemon::PilotDaemon() :
00257     DCOPObject("KPilotDaemonIface"),
00258     fStatus(INIT),
00259     fPostSyncAction(None),
00260     fPilotLink(0L),
00261     fPilotDevice(QString::null),
00262     fNextSyncType(PilotDaemonDCOP::HotSync),
00263     fSyncStack(0L),
00264     fTray(0L),
00265     fInstaller(0L),
00266     fLogStub(new LoggerDCOP_stub("kpilot", "LogIface")),
00267     fKPilotStub(new KPilotDCOP_stub("kpilot", "KPilotIface"))
00268 {
00269     FUNCTIONSETUP;
00270 
00271     setupPilotLink();
00272     reloadSettings();
00273 
00274     if (fStatus == ERROR)
00275     {
00276         kdWarning() << k_funcinfo
00277             << ": Connecting to device failed." << endl;
00278         return;
00279     }
00280 
00281     fInstaller = new FileInstaller;
00282     connect(fInstaller, SIGNAL(filesChanged()),
00283         this, SLOT(slotFilesChanged()));
00284 
00285 
00286 #ifdef DEBUG
00287     DEBUGDAEMON << fname
00288         << ": The daemon is ready with status "
00289         << statusString() << " (" << (int) fStatus << ")" << endl;
00290 #endif
00291 }
00292 
00293 PilotDaemon::~PilotDaemon()
00294 {
00295     FUNCTIONSETUP;
00296 
00297     KPILOT_DELETE(fPilotLink);
00298     KPILOT_DELETE(fSyncStack);
00299     KPILOT_DELETE(fInstaller);
00300 }
00301 
00302 void PilotDaemon::addInstallFiles(const QStringList &l)
00303 {
00304     FUNCTIONSETUP;
00305 
00306     fInstaller->addFiles( l, fTray );
00307 }
00308 
00309 int PilotDaemon::getPilotSpeed(KPilotConfigSettings & config)
00310 {
00311     FUNCTIONSETUP;
00312 
00313     int speed = config.getPilotSpeed();
00314 
00315     // Translate the speed entry in the
00316     // config file to something we can
00317     // put in the environment (for who?)
00318     //
00319     //
00320     const char *speedname = 0L;
00321 
00322     switch (speed)
00323     {
00324     case 0:
00325         speedname = "PILOTRATE=9600";
00326         break;
00327     case 1:
00328         speedname = "PILOTRATE=19200";
00329         break;
00330     case 2:
00331         speedname = "PILOTRATE=38400";
00332         break;
00333     case 3:
00334         speedname = "PILOTRATE=57600";
00335         break;
00336     case 4:
00337         speedname = "PILOTRATE=115200";
00338         break;
00339     default:
00340         speedname = "PILOTRATE=9600";
00341     }
00342 
00343 #ifdef DEBUG
00344     DEBUGDAEMON << fname
00345         << ": Speed set to "
00346         << speedname << " (" << speed << ")" << endl;
00347 #endif
00348 
00349     putenv((char *) speedname);
00350 
00351     return speed;
00352 }
00353 
00354 
00355 void PilotDaemon::showTray()
00356 {
00357     FUNCTIONSETUP;
00358 
00359     if (!fTray)
00360     {
00361 #ifdef DEBUG
00362         DEBUGDAEMON << fname << ": No tray icon to display!" << endl;
00363 #endif
00364 
00365         return;
00366     }
00367 
00368     // Copied from Klipper
00369     KWin::setSystemTrayWindowFor(fTray->winId(), 0);
00370     fTray->setGeometry(-100, -100, 42, 42);
00371     fTray->show();
00372 
00373 #ifdef DEBUG
00374     DEBUGDAEMON << fname << ": Tray icon displayed." << endl;
00375 #endif
00376 
00377     updateTrayStatus();
00378 }
00379 
00380 /* DCOP ASYNC */ void PilotDaemon::reloadSettings()
00381 {
00382     FUNCTIONSETUP;
00383 
00384     switch (fStatus)
00385     {
00386     case INIT:
00387     case HOTSYNC_END:
00388     case ERROR:
00389     case READY:
00390         // It's OK to reload settings in these states.
00391         break;
00392     case HOTSYNC_START:
00393     case FILE_INSTALL_REQ:
00394         // Postpone the reload till the sync finishes.
00395         fPostSyncAction |= ReloadSettings;
00396         return;
00397         break;
00398     }
00399 
00400     KPilotConfigSettings & config = KPilotConfig::getConfig();
00401     config.reparseConfiguration();
00402 
00403     getPilotSpeed(config);
00404 
00405     fPilotDevice = config.getPilotDevice();
00406     fPilotType = KPilotDeviceLink::None;
00407 
00408     (void) PilotAppCategory::setupPilotCodec(config.getEncoding());
00409 
00410 #ifdef DEBUG
00411     DEBUGDAEMON << fname
00412         << ": Got configuration "
00413         << fPilotDevice
00414         << " ("
00415         << fPilotType
00416         << ")"
00417         << endl;
00418 #endif
00419 
00420 
00421     /*
00422     ** Override the kind of device, since OldStyleUSB
00423     ** works with everything and it saves the user from
00424     ** havind to choose the right kind.
00425     */
00426     fPilotType = KPilotDeviceLink::OldStyleUSB;
00427 
00428     if (fPilotLink)
00429     {
00430 #ifdef DEBUG
00431         DEBUGDAEMON << fname
00432             << ": Resetting with device "
00433             << fPilotDevice
00434             << " and type "
00435             << fPilotLink->deviceTypeString(fPilotType) << endl;
00436 #endif
00437 
00438         fPilotLink->reset(fPilotType, fPilotDevice);
00439     }
00440 
00441     if (config.getDockDaemon())
00442     {
00443         if (!fTray)
00444         {
00445             fTray = new PilotDaemonTray(this);
00446             fTray->show();
00447         }
00448         else
00449         {
00450             fTray->show();
00451         }
00452     }
00453     else
00454     {
00455         if (fTray)
00456         {
00457             fTray->hide();
00458             delete fTray;
00459 
00460             fTray = 0L;
00461         }
00462     }
00463 
00464     updateTrayStatus();
00465 }
00466 
00467 /* DCOP */ QString PilotDaemon::statusString()
00468 {
00469     FUNCTIONSETUP;
00470 
00471     QString s = CSL1("PilotDaemon=");
00472 
00473     switch (status())
00474     {
00475     case INIT:
00476         s.append(QString(CSL1("Initializing")));
00477         break;
00478     case READY:
00479         s.append(QString(CSL1("Found device")));
00480         break;
00481     case ERROR:
00482         s.append(QString(CSL1("Error")));
00483         break;
00484     case FILE_INSTALL_REQ:
00485         s.append(QString(CSL1("Installing File")));
00486         break;
00487     case HOTSYNC_END:
00488         s.append(QString(CSL1("End of Hotsync")));
00489         break;
00490     case HOTSYNC_START:
00491         s.append(QString(CSL1("Syncing")));
00492         break;
00493     }
00494 
00495     s.append(CSL1(" NextSync="));
00496     s.append(syncTypeString(fNextSyncType));
00497 
00498     s.append(CSL1(" ("));
00499     if (fPilotLink)
00500     {
00501         s.append(fPilotLink->statusString());
00502     }
00503     s.append(CSL1(")"));
00504 
00505     return s;
00506 }
00507 
00508 
00509 
00510 bool PilotDaemon::setupPilotLink()
00511 {
00512     FUNCTIONSETUP;
00513 
00514     if (fPilotLink)
00515     {
00516         delete fPilotLink;
00517 
00518         fPilotLink = 0;
00519     }
00520 
00521     fPilotLink = KPilotDeviceLink::init();
00522     if (!fPilotLink)
00523     {
00524         kdWarning() << k_funcinfo
00525             << ": Can't get pilot link." << endl;
00526         return false;
00527     }
00528 
00529     QObject::connect(fPilotLink, SIGNAL(deviceReady()),
00530         this, SLOT(startHotSync()));
00531     // connect the signals emitted by the pilotDeviceLink
00532     QObject::connect(fPilotLink, SIGNAL(logError(const QString &)),
00533         this, SLOT(logError(const QString &)));
00534     QObject::connect(fPilotLink, SIGNAL(logMessage(const QString &)),
00535         this, SLOT(logMessage(const QString &)));
00536     QObject::connect(fPilotLink,
00537         SIGNAL(logProgress(const QString &,int)),
00538         this, SLOT(logProgress(const QString &,int)));
00539 
00540 
00541     return true;
00542 }
00543 
00544 
00545 /* DCOP ASYNC */ void PilotDaemon::quitNow()
00546 {
00547     FUNCTIONSETUP;
00548     // Using switch to make sure we cover all the cases.
00549     //
00550     //
00551     switch (fStatus)
00552     {
00553     case INIT:
00554     case HOTSYNC_END:
00555     case ERROR:
00556         getKPilot().daemonStatus(KPilotDCOP::DaemonQuit);
00557         kapp->quit();
00558         break;
00559     case READY:
00560     case HOTSYNC_START:
00561     case FILE_INSTALL_REQ:
00562         fPostSyncAction |= Quit;
00563         break;
00564     }
00565 }
00566 
00567 /* DCOP ASYNC */ void PilotDaemon::requestRegularSyncNext()
00568 {
00569     requestSync(PilotDaemonDCOP::HotSync);
00570 }
00571 
00572 /* DCOP ASYNC */ void PilotDaemon::requestFastSyncNext()
00573 {
00574     requestSync(PilotDaemonDCOP::FastSync);
00575 }
00576 
00577 
00578 /* DCOP ASYNC */ void PilotDaemon::requestSync(int mode)
00579 {
00580     FUNCTIONSETUP;
00581 
00582 #ifdef DEBUG
00583     DEBUGDAEMON << fname
00584         << ": Next sync is: "
00585         << syncTypeString(mode)
00586         << endl ;
00587 #endif
00588 
00589     fNextSyncType = mode;
00590 
00591     updateTrayStatus();
00592 }
00593 
00594 /* DCOP */ int PilotDaemon::nextSyncType() const
00595 {
00596     return fNextSyncType;
00597 }
00598 
00599 QString PilotDaemon::syncTypeString(int i) const
00600 {
00601     FUNCTIONSETUP;
00602     switch (i)
00603     {
00604     case PilotDaemonDCOP::Test:
00605         return QString(CSL1("Test"));
00606     case PilotDaemonDCOP::HotSync:
00607         return QString(CSL1("HotSync"));
00608     case PilotDaemonDCOP::FastSync:
00609         return QString(CSL1("FastSync"));
00610     case PilotDaemonDCOP::Backup:
00611         return QString(CSL1("Backup"));
00612     case PilotDaemonDCOP::Restore:
00613         return QString(CSL1("Restore"));
00614     default:
00615         return QString(CSL1("<unknown>"));
00616     }
00617 }
00618 
00619 /* slot */ void PilotDaemon::startHotSync()
00620 {
00621     FUNCTIONSETUP;
00622 
00623 
00624     if (fTray)
00625     {
00626 #ifdef DEBUG
00627         DEBUGKPILOT << fname << ": Changing tray icon." << endl;
00628 #endif
00629 
00630         fTray->changeIcon(PilotDaemonTray::Busy);
00631     }
00632 
00633     // Tell KPilot what's going on.
00634     getKPilot().daemonStatus(KPilotDCOP::StartOfHotSync);
00635 
00636     fStatus = HOTSYNC_START ;
00637     int mode=0;
00638     bool pcchanged=false;
00639 
00640 #ifdef DEBUG
00641     DEBUGDAEMON << fname
00642         << ": Starting Sync with type "
00643         << syncTypeString(fNextSyncType)
00644         << " (" << fNextSyncType << ")" << endl;
00645 #endif
00646 
00647     KPilotConfigSettings &c = KPilotConfig::getConfig();
00648     QStringList conduits( c.getInstalledConduits() );
00649     if ( (conduits.findIndex( CSL1("internal_fileinstall") ) >= 0) &&
00650         fInstaller) mode |= ActionQueue::WithInstaller;
00651 
00652     // Queue to add all the actions for this sync to.
00653     fSyncStack = new ActionQueue(fPilotLink);
00654 
00655 #ifdef ENABLE_KROUPWARE
00656     bool _syncWithKMail = false;
00657     int _kroupwareParts = 0;
00658 #endif
00659 
00666     int kpilotstatus = getKPilot().kpilotStatus();
00667     DCOPStub::Status callstatus = getKPilot().status();
00668 
00669 #ifdef DEBUG
00670     if (callstatus != DCOPStub::CallSucceeded)
00671     {
00672         DEBUGDAEMON << fname <<
00673             ": Could not call KPilot for status." << endl;
00674     }
00675     else
00676     {
00677         DEBUGDAEMON << fname << ": KPilot status " << kpilotstatus << endl;
00678     }
00679 #endif
00680 
00684     if ((callstatus == DCOPStub::CallSucceeded) &&
00685         (kpilotstatus != KPilotDCOP::WaitingForDaemon))
00686     {
00687         kdWarning() << k_funcinfo <<
00688             ": KPilot returned status " << kpilotstatus << endl;
00689 
00690         fSyncStack->queueInit();
00691         fSyncStack->addAction(new SorryAction(fPilotLink));
00692         // Near the end of this function - sets up
00693         // signal/slot connections and fires off the sync.
00694         goto launch;
00695     }
00696     else
00697     {
00698         fSyncStack->queueInit(ActionQueue::WithUserCheck);
00699     }
00700 
00701 #ifdef ENABLE_KROUPWARE
00702     if ( conduits.findIndex( CSL1("internal_kroupware") ) >= 0 )
00703     {
00704         logMessage( i18n("Kroupware syncing is enabled.") );
00705 
00706         QString errmsg;
00707         if (!KroupwareSync::startKMail(&errmsg))
00708         {
00709             logMessage( i18n("Could not start KMail. The "
00710                 "error message was: %1.").arg(errmsg));
00711         }
00712 
00713         _syncWithKMail = true;
00714 
00715         if (conduits.findIndex( CSL1("vcal-conduit") ) >= 0 )
00716             _kroupwareParts |= KroupwareSync::Cal ;
00717         if (conduits.findIndex( CSL1("todo-conduit") ) >= 0 )
00718             _kroupwareParts |= KroupwareSync::Todo ;
00719         if (conduits.findIndex( CSL1("knotes-conduit") ) >= 0 )
00720             _kroupwareParts |= KroupwareSync::Notes ;
00721         if (conduits.findIndex( CSL1("abbrowser_conduit") ) >= 0 )
00722             _kroupwareParts |= KroupwareSync::Address ;
00723     }
00724 
00725     if (_syncWithKMail)
00726     {
00727         fSyncStack->addAction(new KroupwareSync(true /* pre-sync */,
00728             _kroupwareParts,fPilotLink));
00729     }
00730 #endif
00731 
00732     switch (fNextSyncType)
00733     {
00734     case PilotDaemonDCOP::Test:
00735         fSyncStack->addAction(new TestLink(fPilotLink));
00736         // No conduits, nothing.
00737         break;
00738     case PilotDaemonDCOP::Backup:
00739         mode |= ActionQueue::BackupMode | ActionQueue::FlagFull;
00740         if (conduits.count() > 0)
00741         {
00742             fSyncStack->queueConduits(&KPilotConfig::getConfig(),
00743                 conduits, mode);
00744         }
00745         fSyncStack->addAction(new BackupAction(fPilotLink, mode));
00746         break;
00747     case PilotDaemonDCOP::Restore:
00748         mode |= ActionQueue::RestoreMode | ActionQueue::FlagFull;
00749         fSyncStack->addAction(new RestoreAction(fPilotLink));
00750         if (mode & ActionQueue::WithInstaller)
00751         {
00752             fSyncStack->queueInstaller(fInstaller->dir(),
00753                 fInstaller->fileNames());
00754         }
00755         break;
00756     case PilotDaemonDCOP::HotSync:
00757         // first install the files, and only then do the conduits
00758         // (conduits might want to sync a database that will be installed
00759         mode |= ActionQueue::HotSyncMode;
00760         if (mode & ActionQueue::WithInstaller)
00761         {
00762             fSyncStack->queueInstaller(fInstaller->dir(),
00763                 fInstaller->fileNames());
00764         }
00765         switch (c.getSyncType())
00766         {
00767         case SyncAction::eFastSync:
00768             break;
00769         case SyncAction::eHotSync:
00770             mode |= ActionQueue::WithBackup;
00771             break;
00772         case SyncAction::eFullSync:
00773             mode |= ActionQueue::WithBackup | ActionQueue::FlagFull;
00774             break;
00775         case SyncAction::eCopyPCToHH:
00776             mode |= ActionQueue::FlagPCToHH;
00777             break;
00778         case SyncAction::eCopyHHToPC:
00779             mode |= ActionQueue::FlagHHToPC;
00780             break;
00781         }
00782         if (c.getInternalEditors() && !(mode & ActionQueue::FlagHHToPC) )
00783         {
00784             fSyncStack->addAction(new InternalEditorAction(fPilotLink, mode));
00785         }
00786         // Now check for changed PC
00787         {
00788         KPilotUser *usr = fPilotLink->getPilotUser();
00789         // changing the PC or using a different Palm Desktop app causes a full sync
00790         // Use gethostid for this, since JPilot uses 1+(2000000000.0*random()/(RAND_MAX+1.0))
00791         // as PC_ID, so using JPilot and KPilot is the same as using two differenc PCs
00792         pcchanged = usr->getLastSyncPC() !=(unsigned long) gethostid();
00793         }
00794 
00795         if (conduits.count() > 0)
00796         {
00797             fSyncStack->queueConduits(&KPilotConfig::getConfig(),
00798                 conduits, pcchanged?(mode|ActionQueue::FlagFull):mode);
00799         }
00800         if (pcchanged && c.getFullSyncOnPCChange())
00801             mode |=  (ActionQueue::WithBackup | ActionQueue::FlagFull);
00802 #ifdef DEBUG
00803         DEBUGDAEMON << fname
00804             << ": Sync Mode="
00805             << mode << ", Sync Type="<<c.getSyncType()<<endl;
00806 #endif
00807         if (mode & ActionQueue::WithBackup)
00808             fSyncStack->addAction(new BackupAction(fPilotLink, mode));
00809         break;
00810     default:
00811 #ifdef DEBUG
00812         DEBUGDAEMON << fname
00813             << ": Can't handle sync type "
00814             << syncTypeString(fNextSyncType) << endl;
00815 #endif
00816         break;
00817     }
00818 
00819 #ifdef ENABLE_KROUPWARE
00820     if (_syncWithKMail)
00821     {
00822         fSyncStack->addAction(new KroupwareSync(false /* post-sync */ ,
00823             _kroupwareParts,fPilotLink));
00824     }
00825 #endif
00826 
00827 // Jump here to finalize the connections to the sync action
00828 // queue and start the actual sync.
00829 launch:
00830     fSyncStack->queueCleanup();
00831 
00832     QObject::connect(fSyncStack, SIGNAL(logError(const QString &)),
00833         this, SLOT(logError(const QString &)));
00834     QObject::connect(fSyncStack, SIGNAL(logMessage(const QString &)),
00835         this, SLOT(logMessage(const QString &)));
00836     QObject::connect(fSyncStack,
00837         SIGNAL(logProgress(const QString &,int)),
00838         this, SLOT(logProgress(const QString &,int)));
00839 
00840     QObject::connect(fSyncStack, SIGNAL(syncDone(SyncAction *)),
00841         this, SLOT(endHotSync()));
00842 
00843     QTimer::singleShot(0,fSyncStack,SLOT(execConduit()));
00844 
00845     updateTrayStatus();
00846 }
00847 
00848 /* slot */ void PilotDaemon::logMessage(const QString & s)
00849 {
00850     FUNCTIONSETUPL(2);
00851 
00852     getLogger().logMessage(s);
00853     updateTrayStatus(s);
00854 }
00855 
00856 /* slot */ void PilotDaemon::logError(const QString & s)
00857 {
00858     FUNCTIONSETUP;
00859 
00860     getLogger().logError(s);
00861     updateTrayStatus(s);
00862 }
00863 
00864 /* slot */ void PilotDaemon::logProgress(const QString & s, int i)
00865 {
00866     FUNCTIONSETUPL(2);
00867 
00868     getLogger().logProgress(s, i);
00869     if (!s.isEmpty()) updateTrayStatus(s);
00870 }
00871 
00872 /* slot */ void PilotDaemon::endHotSync()
00873 {
00874     FUNCTIONSETUP;
00875 
00876     if (fTray)
00877     {
00878         QTimer::singleShot(2000,fTray,SLOT(slotShowNormal()));
00879     }
00880 
00881     KPILOT_DELETE(fSyncStack);
00882     fPilotLink->close();
00883 
00884     getLogger().logProgress(i18n("HotSync Completed.<br>"), 100);
00885     getKPilot().daemonStatus(KPilotDCOP::EndOfHotSync);
00886 
00887     fStatus = HOTSYNC_END;
00888 
00889     if (fPostSyncAction & Quit)
00890     {
00891         getKPilot().daemonStatus(KPilotDCOP::DaemonQuit);
00892         kapp->quit();
00893     }
00894     if (fPostSyncAction & ReloadSettings)
00895     {
00896         reloadSettings();
00897     }
00898     else
00899     {
00900         QTimer::singleShot(2000,fPilotLink,SLOT(reset()));
00901     }
00902 
00903     fPostSyncAction = None;
00904 
00905     updateTrayStatus();
00906 }
00907 
00908 
00909 void PilotDaemon::slotFilesChanged()
00910 {
00911     FUNCTIONSETUP;
00912 }
00913 
00914 void PilotDaemon::slotRunKPilot()
00915 {
00916     FUNCTIONSETUP;
00917 
00918     QString kpilotError;
00919     QCString kpilotDCOP;
00920     int kpilotPID;
00921 
00922     if (KApplication::startServiceByDesktopName(CSL1("kpilot"),
00923             QString::null, &kpilotError, &kpilotDCOP, &kpilotPID
00924 #if (KDE_VERSION >= 220)
00925             // Startup notification added in 2.2
00926             , ""
00927 #endif
00928         ))
00929     {
00930         kdWarning() << k_funcinfo
00931             << ": Couldn't start KPilot! " << kpilotError << endl;
00932     }
00933     else
00934     {
00935 #ifdef DEBUG
00936         DEBUGDAEMON << fname
00937             << ": Started KPilot with DCOP name "
00938             << kpilotDCOP << " (pid " << kpilotPID << ")" << endl;
00939 #endif
00940     }
00941 }
00942 
00943 void PilotDaemon::slotRunConduitConfig()
00944 {
00945     FUNCTIONSETUP;
00946 
00947     // This function tries to send the raise() DCOP call to kpilot.
00948     // If it succeeds, we can assume kpilot is running and then try
00949     // to send the configureConduits() DCOP call.
00950     // If it fails (probably because kpilot isn't running) it tries
00951     // to call kpilot via KProcess (using a command line switch to
00952     // only bring up the configure conduits dialog).
00953     //
00954     // Implementing the function this way catches all cases.
00955     // ie 1 KPilot running with configure conduit dialog open (raise())
00956     //    2 KPilot running with dialog NOT open (configureConduits())
00957     //    3 KPilot NOT running (KProcess)
00958 
00959     DCOPClient *client = kapp->dcopClient();
00960 
00961     // This DCOP call to kpilot's raise function solves the final case
00962     // ie when kpilot already has the dialog open
00963 
00964     if (client->send("kpilot", "kpilot-mainwindow#1", "raise()",
00965         QString::null))
00966     {
00967         client->send("kpilot", "KPilotIface", "configureConduits()",
00968             QString::null);
00969     }
00970     else
00971     {
00972         KProcess *p = new KProcess;
00973         *p << "kpilot" << "-c";
00974 
00975         p->start();
00976     }
00977 }
00978 
00979 void PilotDaemon::updateTrayStatus(const QString &s)
00980 {
00981     if (!fTray) return;
00982 
00983     QToolTip::remove(fTray);
00984     QToolTip::add(fTray,
00985         i18n("<qt>%1<br/>%2</qt>")
00986             .arg(statusString())
00987             .arg(s)
00988         );
00989 }
00990 
00991 static KCmdLineOptions daemonoptions[] = {
00992     { "dummy", I18N_NOOP("Dummy command line argument."), 0},
00993 #ifdef DEBUG
00994     {"debug <level>", I18N_NOOP("Set debugging level"), "0"},
00995 #endif
00996     KCmdLineLastOption
00997 } ;
00998 
00999 
01000 int main(int argc, char **argv)
01001 {
01002     FUNCTIONSETUP;
01003 
01004     KAboutData about("kpilotDaemon",
01005         I18N_NOOP("KPilot Daemon"),
01006         KPILOT_VERSION,
01007         "KPilot - HotSync software for KDE\n\n",
01008         KAboutData::License_GPL, "(c) 1998-2001, Dan Pilone");
01009     about.addAuthor("Dan Pilone",
01010         I18N_NOOP("Project Leader"),
01011         "pilone@slac.com", "http://www.slac.com/pilone/kpilot_home/");
01012     about.addAuthor("Adriaan de Groot",
01013         I18N_NOOP("Maintainer"),
01014         "groot@kde.org", "http://www.cs.kun.nl/~adridg/kpilot/");
01015 
01016     KCmdLineArgs::init(argc, argv, &about);
01017     KCmdLineArgs::addCmdLineOptions(daemonoptions,"kpilotconfig");
01018     KUniqueApplication::addCmdLineOptions();
01019     KCmdLineArgs *p = KCmdLineArgs::parsedArgs();
01020 
01021 #ifdef DEBUG
01022     KPilotConfig::getDebugLevel(p);
01023 #endif
01024 
01025     if (!KUniqueApplication::start())
01026     {
01027         return 0;
01028     }
01029     KUniqueApplication a(true, true);
01030 
01031     // A block just to keep variables local.
01032     //
01033     //
01034     {
01035         KPilotConfigSettings & c = KPilotConfig::getConfig();
01036         c.setReadOnly(false);
01037 
01038         if (c.getVersion() < KPilotConfig::ConfigurationVersion)
01039         {
01040             kdError() << k_funcinfo
01041                 << ": Is still not configured for use."
01042                 << endl;
01043             KPilotConfig::sorryVersionOutdated(c.getVersion());
01044             return 1;
01045         }
01046 
01047 #ifdef DEBUG
01048         DEBUGDAEMON << fname
01049             << ": Configuration version "
01050             << c.getVersion() << endl;
01051 #endif
01052     }
01053 
01054 
01055     PilotDaemon *gPilotDaemon = new PilotDaemon();
01056 
01057     if (gPilotDaemon->status() == PilotDaemon::ERROR)
01058     {
01059         delete gPilotDaemon;
01060 
01061         gPilotDaemon = 0;
01062         kdError() << k_funcinfo
01063             << ": **\n"
01064             ": Failed to start up daemon\n"
01065             ": due to errors constructing it.\n" ": **" << endl;
01066         return 2;
01067     }
01068 
01069     gPilotDaemon->showTray();
01070 
01071     return a.exec();
01072 
01073     /* NOTREACHED */
01074     (void) pilotdaemon_id;
01075 }
01076 
01077 
01078 
KDE Logo
This file is part of the documentation for kpilot Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:36:48 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003