summaryrefslogtreecommitdiffstats
path: root/kpilot/pilotDaemon.cc
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2011-02-16 20:17:18 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2011-02-16 20:17:18 +0000
commitcb7eddb91455a69cf66fcd717e91a51ca5e2cfef (patch)
treecf5546e4d7c44370fbe9ca2be937bd254f30ebaa /kpilot/pilotDaemon.cc
downloadkpilot-cb7eddb91455a69cf66fcd717e91a51ca5e2cfef.tar.gz
kpilot-cb7eddb91455a69cf66fcd717e91a51ca5e2cfef.zip
Moved kpilot from kdepim to applications, as the core Trinity libraries should not contain hardware-dependent software
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kpilot@1221127 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'kpilot/pilotDaemon.cc')
-rw-r--r--kpilot/pilotDaemon.cc1404
1 files changed, 1404 insertions, 0 deletions
diff --git a/kpilot/pilotDaemon.cc b/kpilot/pilotDaemon.cc
new file mode 100644
index 0000000..198fe11
--- /dev/null
+++ b/kpilot/pilotDaemon.cc
@@ -0,0 +1,1404 @@
+/* KPilot
+**
+** Copyright (C) 1998-2001 by Dan Pilone
+** Copyright (C) 2001-2004 by Adriaan de Groot
+** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
+**
+** This is the KPilot Daemon, which does the actual communication with
+** the Pilot and with the conduits.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to kde-pim@kde.org
+*/
+
+#include "options.h"
+
+#include <stdlib.h>
+
+#include <tqtimer.h>
+#include <tqtooltip.h>
+#include <tqpixmap.h>
+
+#include <kuniqueapplication.h>
+#include <kaboutapplication.h>
+#include <kcmdlineargs.h>
+#include <kwin.h>
+#include <kurl.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <kprocess.h>
+#include <dcopclient.h>
+#include <kurldrag.h>
+#include <kservice.h>
+#include <kapplication.h>
+#include <khelpmenu.h>
+
+#include "pilotRecord.h"
+
+#include "fileInstaller.h"
+#include "pilotUser.h"
+#include "pilotDatabase.h"
+#include "kpilotlink.h"
+#include "kpilotdevicelink.h"
+#include "actionQueue.h"
+#include "actions.h"
+
+#include "hotSync.h"
+#include "internalEditorAction.h"
+#include "logFile.h"
+
+#include "kpilotConfig.h"
+
+
+#include "kpilotDCOP_stub.h"
+#include "kpilotDCOP.h"
+#include "loggerDCOP_stub.h"
+
+#include "pilotDaemon.moc"
+
+static KAboutData *aboutData = 0L;
+
+PilotDaemonTray::PilotDaemonTray(PilotDaemon * p) :
+ KSystemTray(0, "pilotDaemon"),
+ fSyncTypeMenu(0L),
+ daemon(p),
+ kap(0L),
+ fBlinkTimer(0L)
+{
+ FUNCTIONSETUP;
+ setupWidget();
+ setAcceptDrops(true);
+}
+
+/* virtual */ void PilotDaemonTray::dragEnterEvent(TQDragEnterEvent * e)
+{
+ FUNCTIONSETUP;
+ e->accept(KURLDrag::canDecode(e));
+}
+
+/* virtual */ void PilotDaemonTray::dropEvent(TQDropEvent * e)
+{
+ FUNCTIONSETUP;
+
+ KURL::List list;
+
+ KURLDrag::decode(e, list);
+
+ TQStringList files;
+ for(KURL::List::ConstIterator it = list.begin(); it != list.end(); ++it)
+ {
+ if ((*it).isLocalFile())
+ files << (*it).path();
+ }
+
+ daemon->addInstallFiles(files);
+}
+
+/* virtual */ void PilotDaemonTray::mousePressEvent(TQMouseEvent * e)
+{
+ FUNCTIONSETUP;
+
+ switch (e->button())
+ {
+ case RightButton:
+ {
+ KPopupMenu *menu = contextMenu();
+ contextMenuAboutToShow(menu);
+ menu->popup(e->globalPos());
+ }
+ break;
+ case LeftButton:
+ if (daemon) daemon->slotRunKPilot();
+ break;
+ default:
+ KSystemTray::mousePressEvent(e);
+ }
+}
+
+/* virtual */ void PilotDaemonTray::closeEvent(TQCloseEvent *)
+{
+ FUNCTIONSETUP;
+ daemon->quitNow();
+}
+
+void PilotDaemonTray::setupWidget()
+{
+ FUNCTIONSETUP;
+
+ KGlobal::iconLoader()->addAppDir( CSL1("kpilot") );
+ icons[Normal] = loadIcon( CSL1("kpilotDaemon") );
+ icons[Busy] = loadIcon( CSL1("busysync") );
+ icons[NotListening] = loadIcon( CSL1("nosync") );
+
+ slotShowNotListening();
+ TQTimer::singleShot(2000,this,TQT_SLOT(slotShowNormal()));
+
+ KPopupMenu *menu = contextMenu();
+
+ menuKPilotItem = menu->insertItem(i18n("Start &KPilot"), daemon,
+ TQT_SLOT(slotRunKPilot()));
+ menuConfigureConduitsItem = menu->insertItem(i18n("&Configure KPilot..."),
+ daemon, TQT_SLOT(slotRunConfig()));
+ menu->insertSeparator();
+
+ fSyncTypeMenu = new KPopupMenu(menu,"sync_type_menu");
+ TQString once = i18n("Appended to names of sync types to indicate the sync will happen just one time"," (once)");
+#define MI(a) fSyncTypeMenu->insertItem( \
+ SyncAction::SyncMode::name(SyncAction::SyncMode::a) + once, \
+ (int)(SyncAction::SyncMode::a));
+ fSyncTypeMenu->insertItem(i18n("Default (%1)")
+ .arg(SyncAction::SyncMode::name((SyncAction::SyncMode::Mode)KPilotSettings::syncType())),
+ 0);
+ fSyncTypeMenu->insertSeparator();
+
+ // Keep this synchronized with kpilotui.rc and kpilot.cc if at all possible.
+ MI(eHotSync);
+ MI(eFullSync);
+ MI(eBackup);
+ MI(eRestore);
+ MI(eCopyHHToPC);
+ MI(eCopyPCToHH);
+
+ fSyncTypeMenu->setCheckable(true);
+ fSyncTypeMenu->setItemChecked(0,true);
+#undef MI
+ connect(fSyncTypeMenu,TQT_SIGNAL(activated(int)),daemon,TQT_SLOT(requestSync(int)));
+ menu->insertItem(i18n("Next &Sync"),fSyncTypeMenu);
+
+ KHelpMenu *help = new KHelpMenu(menu,aboutData);
+ menu->insertItem(
+ KGlobal::iconLoader()->loadIconSet(CSL1("help"),KIcon::Small,0,true),
+ i18n("&Help"),help->menu(),false /* no whatsthis */);
+
+
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Finished getting icons" << endl;
+#endif
+}
+
+void PilotDaemonTray::slotShowAbout()
+{
+ FUNCTIONSETUP;
+
+ if (!kap)
+ {
+ kap = new KAboutApplication(0, "kpdab", false);
+ }
+
+ kap->show();
+}
+
+
+void PilotDaemonTray::enableRunKPilot(bool b)
+{
+ FUNCTIONSETUP;
+ contextMenu()->setItemEnabled(menuKPilotItem, b);
+ contextMenu()->setItemEnabled(menuConfigureConduitsItem, b);
+}
+
+
+void PilotDaemonTray::changeIcon(IconShape i)
+{
+ FUNCTIONSETUP;
+ if (icons[i].isNull())
+ {
+ WARNINGKPILOT << "Icon #"<<i<<" is NULL!" << endl;
+ }
+ setPixmap(icons[i]);
+ fCurrentIcon = i;
+}
+
+void PilotDaemonTray::slotShowNormal()
+{
+ FUNCTIONSETUP;
+ changeIcon(Normal);
+}
+
+void PilotDaemonTray::slotShowBusy()
+{
+ FUNCTIONSETUP;
+ changeIcon(Busy);
+}
+
+void PilotDaemonTray::slotShowNotListening()
+{
+ FUNCTIONSETUP;
+ changeIcon( NotListening );
+}
+
+void PilotDaemonTray::slotBusyTimer()
+{
+ if (fCurrentIcon == Busy) changeIcon(Normal);
+ else if (fCurrentIcon == Normal) changeIcon(Busy);
+}
+
+void PilotDaemonTray::startHotSync()
+{
+ changeIcon(Busy);
+ if (!fBlinkTimer)
+ {
+ fBlinkTimer = new TQTimer(this,"blink timer");
+ }
+ if (fBlinkTimer)
+ {
+ connect(fBlinkTimer,TQT_SIGNAL(timeout()),
+ this,TQT_SLOT(slotBusyTimer()));
+ fBlinkTimer->start(750,false);
+ }
+}
+
+void PilotDaemonTray::endHotSync()
+{
+ changeIcon(Normal);
+ if (fBlinkTimer)
+ {
+ fBlinkTimer->stop();
+ }
+}
+
+
+PilotDaemon::PilotDaemon() :
+ DCOPObject("KPilotDaemonIface"),
+ fDaemonStatus(INIT),
+ fPostSyncAction(None),
+ fPilotLink(0L),
+ fNextSyncType(SyncAction::SyncMode::eHotSync,true),
+ fSyncStack(0L),
+ fTray(0L),
+ fInstaller(0L),
+ fLogFile(0L),
+ fLogStub(new LoggerDCOP_stub("kpilot", "LogIface")),
+ fLogFileStub(new LoggerDCOP_stub("kpilotDaemon", "LogIface")),
+ fKPilotStub(new KPilotDCOP_stub("kpilot", "KPilotIface")),
+ fTempDevice(TQString::null)
+{
+ FUNCTIONSETUP;
+
+ setupPilotLink();
+ reloadSettings();
+
+ if (fDaemonStatus == ERROR)
+ {
+ WARNINGKPILOT << "Connecting to device failed." << endl;
+ return;
+ }
+
+ fInstaller = new FileInstaller;
+ fLogFile = new LogFile;
+ connect(fInstaller, TQT_SIGNAL(filesChanged()),
+ this, TQT_SLOT(slotFilesChanged()));
+
+ fNextSyncType.setMode( KPilotSettings::syncType() );
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": The daemon is ready with status "
+ << statusString() << " (" << (int) fDaemonStatus << ")" << endl;
+#endif
+}
+
+PilotDaemon::~PilotDaemon()
+{
+ FUNCTIONSETUP;
+
+ KPILOT_DELETE(fPilotLink);
+ KPILOT_DELETE(fSyncStack);
+ KPILOT_DELETE(fInstaller);
+
+ (void) PilotDatabase::instanceCount();
+}
+
+void PilotDaemon::addInstallFiles(const TQStringList &l)
+{
+ FUNCTIONSETUP;
+
+ fInstaller->addFiles( l, fTray );
+}
+
+int PilotDaemon::getPilotSpeed()
+{
+ FUNCTIONSETUP;
+
+ int speed = KPilotSettings::pilotSpeed();
+
+ // Translate the speed entry in the
+ // config file to something we can
+ // put in the environment (for who?)
+ //
+ //
+ const char *speedname = 0L;
+
+ switch (speed)
+ {
+ case 0:
+ speedname = "PILOTRATE=9600";
+ break;
+ case 1:
+ speedname = "PILOTRATE=19200";
+ break;
+ case 2:
+ speedname = "PILOTRATE=38400";
+ break;
+ case 3:
+ speedname = "PILOTRATE=57600";
+ break;
+ case 4:
+ speedname = "PILOTRATE=115200";
+ break;
+ default:
+ speedname = "PILOTRATE=9600";
+ }
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Speed set to "
+ << speedname << " (" << speed << ")" << endl;
+#endif
+
+ putenv((char *) speedname);
+
+ return speed;
+}
+
+
+void PilotDaemon::showTray()
+{
+ FUNCTIONSETUP;
+
+ if (!fTray)
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": No tray icon to display!" << endl;
+#endif
+
+ return;
+ }
+
+ // Copied from Klipper
+ KWin::setSystemTrayWindowFor(fTray->winId(), 0);
+ fTray->setGeometry(-100, -100, 42, 42);
+ fTray->show();
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Tray icon displayed." << endl;
+#endif
+
+ updateTrayStatus();
+}
+
+/* DCOP ASYNC */ void PilotDaemon::setTempDevice(TQString d)
+{
+ if ( !d.isEmpty() ){
+ fTempDevice = d;
+ if (fPilotLink)
+ fPilotLink->setTempDevice( fTempDevice );
+ reloadSettings();
+ }
+}
+
+/* DCOP ASYNC */ void PilotDaemon::reloadSettings()
+{
+ FUNCTIONSETUP;
+
+ switch (fDaemonStatus)
+ {
+ case INIT:
+ case HOTSYNC_END:
+ case ERROR:
+ case READY:
+ case NOT_LISTENING:
+ // It's OK to reload settings in these states.
+ break;
+ case HOTSYNC_START:
+ case FILE_INSTALL_REQ:
+ // Postpone the reload till the sync finishes.
+ fPostSyncAction |= ReloadSettings;
+ return;
+ break;
+ }
+
+ // TODO: Is this bunch of calls really necessary to reload the settings???
+ delete KPilotSettings::self();
+ KPilotSettings::self()->config()->reparseConfiguration();
+ KPilotSettings::self()->readConfig();
+ getPilotSpeed();
+
+ (void) Pilot::setupPilotCodec(KPilotSettings::encoding());
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Got configuration "
+ << KPilotSettings::pilotDevice()
+ << endl;
+ DEBUGKPILOT << fname
+ << ": Got conduit list "
+ << (KPilotSettings::installedConduits().join(CSL1(",")))
+ << endl;
+#endif
+
+ requestSync(0);
+
+
+ if (fPilotLink)
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Resetting with device "
+ << KPilotSettings::pilotDevice()
+ << endl;
+#endif
+
+ fPilotLink->reset( KPilotSettings::pilotDevice() );
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Using workarounds "
+ << KPilotSettings::workarounds()
+ << endl;
+#endif
+ if ( KPilotSettings::workarounds() == KPilotSettings::eWorkaroundUSB )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Using Zire31 USB workaround." << endl;
+#endif
+ fPilotLink->setWorkarounds(true);
+ }
+ }
+
+ if (KPilotSettings::dockDaemon())
+ {
+ if (!fTray)
+ {
+ fTray = new PilotDaemonTray(this);
+ fTray->show();
+ }
+ else
+ {
+ fTray->show();
+ }
+ }
+ else
+ {
+ if (fTray)
+ {
+ fTray->hide();
+ delete fTray;
+
+ fTray = 0L;
+ }
+ }
+
+ updateTrayStatus();
+ logProgress(TQString::null,0);
+}
+
+/* DCOP */ void PilotDaemon::stopListening()
+{
+ fIsListening=false;
+ fTray->changeIcon(PilotDaemonTray::NotListening);
+ fDaemonStatus=NOT_LISTENING;
+ fPilotLink->close();
+}
+
+/* DCOP */ void PilotDaemon::startListening()
+{
+ fIsListening=true;
+ fTray->changeIcon(PilotDaemonTray::Normal);
+ fDaemonStatus=INIT;
+ fPilotLink->reset();
+}
+
+/* DCOP */ TQString PilotDaemon::statusString()
+{
+ FUNCTIONSETUP;
+
+ TQString s = CSL1("PilotDaemon=");
+ s.append(shorStatusString());
+
+ s.append(CSL1("; NextSync="));
+ s.append(fNextSyncType.name());
+
+ s.append(CSL1(" ("));
+ if (fPilotLink)
+ {
+ s.append(fPilotLink->statusString());
+ }
+ s.append(CSL1(");"));
+
+ return s;
+}
+
+/* DCOP */ TQString PilotDaemon::shorStatusString()
+{
+ TQString s;
+
+ switch (status())
+ {
+ case INIT:
+ s.append(CSL1("Waiting for sync"));
+ break;
+ case READY:
+ s.append(CSL1("Listening on device"));
+ break;
+ case ERROR:
+ s=CSL1("Error");
+ break;
+ case FILE_INSTALL_REQ:
+ s=CSL1("Installing File");
+ break;
+ case HOTSYNC_END:
+ s=CSL1("End of Hotsync");
+ break;
+ case HOTSYNC_START:
+ s=CSL1("Syncing");
+ break;
+ case NOT_LISTENING:
+ s.append(CSL1("Not Listening (stopped manually)"));
+ break;
+ }
+
+ return s;
+}
+
+
+
+bool PilotDaemon::setupPilotLink()
+{
+ FUNCTIONSETUP;
+
+ KPILOT_DELETE(fPilotLink);
+ fPilotLink = new KPilotDeviceLink( 0, 0, fTempDevice );
+ if (!fPilotLink)
+ {
+ WARNINGKPILOT << "Can't get pilot link." << endl;
+ return false;
+ }
+
+ TQObject::connect(fPilotLink, TQT_SIGNAL(deviceReady(KPilotLink*)),
+ this, TQT_SLOT(startHotSync(KPilotLink*)));
+ // connect the signals emitted by the pilotDeviceLink
+ TQObject::connect(fPilotLink, TQT_SIGNAL(logError(const TQString &)),
+ this, TQT_SLOT(logError(const TQString &)));
+ TQObject::connect(fPilotLink, TQT_SIGNAL(logMessage(const TQString &)),
+ this, TQT_SLOT(logMessage(const TQString &)));
+ TQObject::connect(fPilotLink,
+ TQT_SIGNAL(logProgress(const TQString &,int)),
+ this, TQT_SLOT(logProgress(const TQString &,int)));
+
+
+ return true;
+}
+
+
+/* DCOP ASYNC */ void PilotDaemon::quitNow()
+{
+ FUNCTIONSETUP;
+ // Using switch to make sure we cover all the cases.
+ //
+ //
+ switch (fDaemonStatus)
+ {
+ case INIT:
+ case HOTSYNC_END:
+ case ERROR:
+ case NOT_LISTENING:
+ getKPilot().daemonStatus(KPilotDCOP::DaemonQuit);
+ kapp->quit();
+ break;
+ case READY:
+ case HOTSYNC_START:
+ case FILE_INSTALL_REQ:
+ fPostSyncAction |= Quit;
+ break;
+ }
+ emitDCOPSignal( "kpilotDaemonStatusChanged()", TQByteArray() );
+}
+
+/* DCOP ASYNC */ void PilotDaemon::requestRegularSyncNext()
+{
+ requestSync(SyncAction::SyncMode::eHotSync);
+}
+
+
+/* DCOP ASYNC */ void PilotDaemon::requestSync(int mode)
+{
+ FUNCTIONSETUP;
+
+ if ( 0==mode )
+ {
+ mode = KPilotSettings::syncType();
+ }
+
+ if ( !fNextSyncType.setMode(mode) )
+ {
+ WARNINGKPILOT << "Ignored fake sync type " << mode << endl;
+ return;
+ }
+
+ updateTrayStatus();
+
+ if (fTray && (fTray->fSyncTypeMenu))
+ {
+ for (int i=((int)SyncAction::SyncMode::eHotSync);
+ i<=((int)SyncAction::SyncMode::eRestore) /* Restore */ ;
+ ++i)
+ {
+ fTray->fSyncTypeMenu->setItemChecked(i,mode==i);
+ }
+ }
+
+ getLogger().logMessage(i18n("Next HotSync will be: %1. ").arg(fNextSyncType.name()) +
+ i18n("Please press the HotSync button."));
+}
+
+/* DCOP ASYNC */ void PilotDaemon::requestSyncType(TQString s)
+{
+ FUNCTIONSETUP;
+
+ // This checks unique prefixes of the names of the various sync types.
+ if (s.startsWith(CSL1("H"))) requestSync(SyncAction::SyncMode::eHotSync);
+ else if (s.startsWith(CSL1("Fu"))) requestSync(SyncAction::SyncMode::eFullSync);
+ else if (s.startsWith(CSL1("B"))) requestSync(SyncAction::SyncMode::eBackup);
+ else if (s.startsWith(CSL1("R"))) requestSync(SyncAction::SyncMode::eRestore);
+ else if (s.startsWith(CSL1("T"))) { fNextSyncType.setOptions(true,false); }
+ else if (s.startsWith(CSL1("CopyHHToPC"))) requestSync(SyncAction::SyncMode::eCopyHHToPC);
+ else if (s.startsWith(CSL1("CopyPCToHH"))) requestSync(SyncAction::SyncMode::eCopyPCToHH);
+ else if (s.startsWith(CSL1("D"))) requestSync(0);
+ else
+ {
+ WARNINGKPILOT << "Unknown sync type " << ( s.isEmpty() ? CSL1("<none>") : s )
+ << endl;
+ }
+}
+
+/* DCOP ASYNC */ void PilotDaemon::requestSyncOptions(bool test, bool local)
+{
+ if ( !fNextSyncType.setOptions(test,local) )
+ {
+ WARNINGKPILOT << "Nonsensical request for "
+ << (test ? "test" : "notest")
+ << ' '
+ << (local ? "local" : "nolocal")
+ << " in mode "
+ << fNextSyncType.name() << endl;
+ }
+}
+
+/* DCOP */ int PilotDaemon::nextSyncType() const
+{
+ return fNextSyncType.mode();
+}
+
+/**
+* DCOP Functions reporting some status data, e.g. for the kontact plugin.
+*/
+TQDateTime PilotDaemon::lastSyncDate()
+{
+ return KPilotSettings::lastSyncTime();
+}
+
+
+static TQDict<TQString> *conduitNameMap = 0L;
+
+static void fillConduitNameMap()
+{
+ if ( !conduitNameMap )
+ {
+ conduitNameMap = new TQDict<TQString>;
+ conduitNameMap->setAutoDelete(true);
+ }
+ conduitNameMap->clear();
+
+ TQStringList l = KPilotSettings::installedConduits();
+ // Fill with internal settings.
+ if ( l.find( CSL1("internal_fileinstall") ) != l.end() ) {
+ conduitNameMap->insert( CSL1("internal_fileinstall"),
+ new TQString(i18n("File Installer")) );
+ }
+
+ TQStringList::ConstIterator end = l.end();
+ for (TQStringList::ConstIterator i = l.begin(); i != end; ++i)
+ {
+ if (!conduitNameMap->find(*i))
+ {
+ TQString readableName = CSL1("<unknown>");
+ KSharedPtr < KService > o = KService::serviceByDesktopName(*i);
+ if (!o)
+ {
+ WARNINGKPILOT << "No service for " << *i << endl;
+ }
+ else
+ {
+ readableName = o->name();
+ }
+ conduitNameMap->insert( *i, new TQString(readableName) );
+ }
+ }
+}
+
+
+TQStringList PilotDaemon::configuredConduitList()
+{
+ fillConduitNameMap();
+
+ TQStringList keys;
+
+ TQDictIterator<TQString> it(*conduitNameMap);
+ for ( ; *it; ++it)
+ {
+ keys << it.currentKey();
+ }
+ keys.sort();
+
+ TQStringList::ConstIterator end = keys.end();
+ TQStringList result;
+ for (TQStringList::ConstIterator i = keys.begin(); i != end; ++i)
+ {
+ result << *(conduitNameMap->find(*i));
+ }
+
+ return result;
+}
+
+TQString PilotDaemon::logFileName()
+{
+ return KPilotSettings::logFileName();
+}
+
+TQString PilotDaemon::userName()
+{
+ return KPilotSettings::userName();
+}
+TQString PilotDaemon::pilotDevice()
+{
+ return KPilotSettings::pilotDevice();
+}
+
+bool PilotDaemon::killDaemonOnExit()
+{
+ return KPilotSettings::killDaemonAtExit();
+}
+
+typedef enum { NotLocked=0, Locked=1, DCOPError=2 } KDesktopLockStatus;
+static KDesktopLockStatus isKDesktopLockRunning()
+{
+ if (!KPilotSettings::screenlockSecure()) return NotLocked;
+
+ DCOPClient *dcopptr = KApplication::kApplication()->dcopClient();
+
+ // Can't tell, very weird, err on the side of safety.
+ if (!dcopptr || !dcopptr->isAttached())
+ {
+ WARNINGKPILOT << "Could not make DCOP connection. "
+ << "Assuming screensaver is active." << endl;
+ return DCOPError;
+ }
+
+ TQByteArray data,returnValue;
+ TQCString returnType;
+
+ if (!dcopptr->call("kdesktop","KScreensaverIface","isBlanked()",
+ data,returnType,returnValue,true))
+ {
+ WARNINGKPILOT << "Check for screensaver failed."
+ << "Assuming screensaver is active." << endl;
+ // Err on the side of safety again.
+ return DCOPError;
+ }
+
+ if (returnType == "bool")
+ {
+ bool b;
+ TQDataStream reply(returnValue,IO_ReadOnly);
+ reply >> b;
+ return (b ? Locked : NotLocked);
+ }
+ else
+ {
+ WARNINGKPILOT << "Strange return value from screensaver. "
+ << "Assuming screensaver is active." << endl;
+ // Err on the side of safety.
+ return DCOPError;
+ }
+}
+
+
+static void informOthers(KPilotDCOP_stub &kpilot,
+ LoggerDCOP_stub &log,
+ LoggerDCOP_stub &filelog)
+{
+ kpilot.daemonStatus(KPilotDCOP::StartOfHotSync);
+ log.logStartSync();
+ filelog.logStartSync();
+}
+
+static bool isSyncPossible(ActionQueue *fSyncStack,
+ KPilotLink *pilotLink,
+ KPilotDCOP_stub &kpilot)
+{
+ FUNCTIONSETUP;
+
+ /**
+ * If KPilot is busy with something - like configuring
+ * conduit - then we shouldn't run a real sync, but
+ * just tell the user that the sync couldn't run because
+ * of that.
+ */
+ int kpilotstatus = kpilot.kpiloStatus();
+ DCOPStub::Status callstatus = kpilot.status();
+
+#ifdef DEBUG
+ if (callstatus != DCOPStub::CallSucceeded)
+ {
+ DEBUGKPILOT << fname <<
+ ": Could not call KPilot for status." << endl;
+ }
+ else
+ {
+ DEBUGKPILOT << fname << ": KPilot status " << kpilotstatus << endl;
+ }
+#endif
+ /**
+ * If the call fails, then KPilot is probably not running
+ * and we can behave normally.
+ */
+ if ((callstatus == DCOPStub::CallSucceeded) &&
+ (kpilotstatus != KPilotDCOP::WaitingForDaemon))
+ {
+ WARNINGKPILOT << "KPilot returned status " << kpilotstatus << endl;
+
+ fSyncStack->queueInit();
+ fSyncStack->addAction(new SorryAction(pilotLink));
+ return false;
+ }
+
+ switch (isKDesktopLockRunning())
+ {
+ case NotLocked :
+ break; /* Fall through to return true below */
+ case Locked :
+ fSyncStack->queueInit();
+ fSyncStack->addAction(new SorryAction(pilotLink,
+ i18n("HotSync is disabled while the screen is locked.")));
+ return false;
+ case DCOPError :
+ fSyncStack->queueInit();
+ fSyncStack->addAction(new SorryAction(pilotLink,
+ i18n("HotSync is disabled because KPilot could not "
+ "determine the state of the screen saver. You "
+ "can disable this security feature by unchecking "
+ "the 'do not sync when screensaver is active' box "
+ "in the HotSync page of the configuration dialog.")));
+ return false;
+ }
+
+ return true;
+}
+
+static void queueInstaller(ActionQueue *fSyncStack,
+ KPilotLink *pilotLink,
+ FileInstaller *fInstaller,
+ const TQStringList &c)
+{
+ if (c.findIndex(CSL1("internal_fileinstall")) >= 0)
+ {
+ fSyncStack->addAction(new FileInstallAction(pilotLink,fInstaller->dir()));
+ }
+}
+
+static void queueEditors(ActionQueue *fSyncStack, KPilotLink *pilotLink)
+{
+ if (KPilotSettings::internalEditors())
+ {
+ fSyncStack->addAction(new InternalEditorAction(pilotLink));
+ }
+}
+
+static void queueConduits(ActionQueue *fSyncStack,
+ const TQStringList &conduits,
+ SyncAction::SyncMode e)
+{
+ if (conduits.count() > 0)
+ {
+ fSyncStack->queueConduits(conduits,e);
+ // TQString s = i18n("Conduit flags: ");
+ // s.append(ConduitProxy::flagsForMode(e).join(CSL1(" ")));
+ // logMessage(s);
+ }
+}
+
+bool PilotDaemon::shouldBackup()
+{
+
+ FUNCTIONSETUP;
+
+ bool ret = false;
+ int backupfreq = KPilotSettings::backupFrequency();
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Backup Frequency is: [" << backupfreq <<
+ "]. " << endl;
+#endif
+
+ if ( (fNextSyncType == SyncAction::SyncMode::eHotSync) ||
+ (fNextSyncType == SyncAction::SyncMode::eFullSync) )
+ {
+ /** If we're doing a Hot or Full sync, see if our user has
+ * configured us to or to not always do a backup.
+ */
+ if ( backupfreq == SyncAction::eOnRequestOnly )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Should not do backup..." << endl;
+#endif
+ ret = false;
+ }
+ else if ( backupfreq == SyncAction::eEveryHotSync )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Should do backup..." << endl;
+#endif
+ ret = true;
+ }
+ }
+
+ return ret;
+
+}
+
+
+/* slot */ void PilotDaemon::startHotSync(KPilotLink *pilotLink)
+{
+ FUNCTIONSETUP;
+
+ bool pcchanged=false; // If last PC to sync was a different one (implies full sync, normally)
+ TQStringList conduits ; // list of conduits to run
+ TQString s; // a generic string for stuff
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Starting Sync with type "
+ << fNextSyncType.name() << endl;
+ DEBUGKPILOT << fname << ": Status is " << shorStatusString() << endl;
+ (void) PilotDatabase::instanceCount();
+#endif
+
+ fDaemonStatus = HOTSYNC_START ;
+ if (fTray)
+ {
+ fTray->startHotSync();
+ }
+ informOthers(getKPilot(),getLogger(),getFileLogger());
+
+
+ // Queue to add all the actions for this sync to.
+ fSyncStack = new ActionQueue(pilotLink);
+
+ // Check if the sync is possible at all.
+ if (!isSyncPossible(fSyncStack,pilotLink,getKPilot()))
+ {
+ // Sync is not possible now, sorry action was added to
+ // the queue, and we run that -- skipping all the rest of the sync stuff.
+ goto launch;
+ }
+
+ // Except when the user has requested a Restore, in which case she knows she doesn't
+ // want to sync with a blank palm and then back up the result over her stored backup files,
+ // do a Full Sync when changing the PC or using a different Palm Desktop app.
+ if (fNextSyncType.mode() != SyncAction::SyncMode::eRestore)
+ { // Use gethostid to determine , since JPilot uses 1+(2000000000.0*random()/(RAND_MAX+1.0))
+ // as PC_ID, so using JPilot and KPilot is the same as using two different PCs
+ KPilotUser &usr = pilotLink->getPilotUser();
+ pcchanged = usr.getLastSyncPC() !=(unsigned long) gethostid();
+
+ if (pcchanged)
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": PC changed. Last sync PC: [" << usr.getLastSyncPC()
+ << "], me: [" << (unsigned long) gethostid() << "]" << endl;
+#endif
+ if ( KPilotSettings::fullSyncOnPCChange() )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Setting sync mode to full sync. " << endl;
+#endif
+ fNextSyncType = SyncAction::SyncMode::eFullSync;
+ }
+ else
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Not changing sync mode because of settings. " << endl;
+#endif
+ }
+ }
+ }
+
+ // Normal case: regular sync.
+ fSyncStack->queueInit();
+ fSyncStack->addAction(new CheckUser(pilotLink));
+
+ conduits = KPilotSettings::installedConduits() ;
+
+ if (fNextSyncType.isTest())
+ {
+ fSyncStack->addAction(new TestLink(pilotLink));
+ }
+ else
+ {
+ switch (fNextSyncType.mode())
+ {
+ case SyncAction::SyncMode::eBackup:
+ if (KPilotSettings::runConduitsWithBackup() && (conduits.count() > 0))
+ {
+ queueConduits(fSyncStack,conduits,fNextSyncType);
+ }
+ fSyncStack->addAction(new BackupAction(pilotLink,true));
+ break;
+ case SyncAction::SyncMode::eRestore:
+ fSyncStack->addAction(new RestoreAction(pilotLink));
+ queueInstaller(fSyncStack,pilotLink,fInstaller,conduits);
+ break;
+ case SyncAction::SyncMode::eFullSync:
+ case SyncAction::SyncMode::eHotSync:
+ // first install the files, and only then do the conduits
+ // (conduits might want to sync a database that will be installed
+ queueInstaller(fSyncStack,pilotLink,fInstaller,conduits);
+ queueEditors(fSyncStack,pilotLink);
+ queueConduits(fSyncStack,conduits,fNextSyncType);
+ // After running the conduits, install new databases
+ queueInstaller(fSyncStack,pilotLink,fInstaller,conduits);
+ // And sync the remaining databases if needed.
+ if (shouldBackup())
+ {
+ fSyncStack->addAction(new BackupAction(pilotLink, (fNextSyncType == SyncAction::SyncMode::eFullSync)));
+ }
+ break;
+ case SyncAction::SyncMode::eCopyPCToHH:
+ queueConduits(fSyncStack,conduits,SyncAction::SyncMode::eCopyPCToHH);
+ break;
+ case SyncAction::SyncMode::eCopyHHToPC:
+ queueConduits(fSyncStack,conduits,SyncAction::SyncMode::eCopyHHToPC);
+ break;
+ }
+ }
+
+// Jump here to finalize the connections to the sync action
+// queue and start the actual sync.
+launch:
+ fSyncStack->queueCleanup();
+
+ TQObject::connect(fSyncStack, TQT_SIGNAL(logError(const TQString &)),
+ this, TQT_SLOT(logError(const TQString &)));
+ TQObject::connect(fSyncStack, TQT_SIGNAL(logMessage(const TQString &)),
+ this, TQT_SLOT(logMessage(const TQString &)));
+ TQObject::connect(fSyncStack,
+ TQT_SIGNAL(logProgress(const TQString &,int)),
+ this, TQT_SLOT(logProgress(const TQString &,int)));
+
+ TQObject::connect(fSyncStack, TQT_SIGNAL(syncDone(SyncAction *)),
+ this, TQT_SLOT(endHotSync()));
+
+ TQTimer::singleShot(0,fSyncStack,TQT_SLOT(execConduit()));
+
+ updateTrayStatus();
+}
+
+/* slot */ void PilotDaemon::logMessage(const TQString & s)
+{
+ FUNCTIONSETUPL(2);
+
+ getLogger().logMessage(s);
+ getFileLogger().logMessage(s);
+ updateTrayStatus(s);
+}
+
+/* slot */ void PilotDaemon::logError(const TQString & s)
+{
+ FUNCTIONSETUP;
+
+ getLogger().logError(s);
+ getFileLogger().logError(s);
+ updateTrayStatus(s);
+}
+
+/* slot */ void PilotDaemon::logProgress(const TQString & s, int i)
+{
+ FUNCTIONSETUPL(2);
+
+ getLogger().logProgress(s, i);
+ getFileLogger().logProgress(s, i);
+ if (!s.isEmpty()) updateTrayStatus(s);
+}
+
+/* slot */ void PilotDaemon::endHotSync()
+{
+ FUNCTIONSETUP;
+
+ if (fTray)
+ {
+ fTray->endHotSync();
+ }
+
+ KPILOT_DELETE(fSyncStack);
+ fPilotLink->close();
+
+ getLogger().logProgress(i18n("HotSync Completed.<br>"), 100);
+ getFileLogger().logProgress(i18n("HotSync Completed.<br>"), 100);
+ getLogger().logEndSync();
+ getFileLogger().logEndSync();
+ getKPilot().daemonStatus(KPilotDCOP::EndOfHotSync);
+ KPilotSettings::setLastSyncTime(TQDateTime::tqcurrentDateTime());
+ KPilotSettings::self()->writeConfig();
+
+ fDaemonStatus = HOTSYNC_END;
+
+ if (fPostSyncAction & Quit)
+ {
+ getKPilot().daemonStatus(KPilotDCOP::DaemonQuit);
+ kapp->quit();
+ }
+ if (fPostSyncAction & ReloadSettings)
+ {
+ reloadSettings();
+ }
+ else
+ {
+ TQTimer::singleShot(10000,fPilotLink,TQT_SLOT(reset()));
+ }
+
+ fPostSyncAction = None;
+ requestSync(0);
+
+ (void) PilotDatabase::instanceCount();
+
+ updateTrayStatus();
+}
+
+
+void PilotDaemon::slotFilesChanged()
+{
+ FUNCTIONSETUP;
+}
+
+void PilotDaemon::slotRunKPilot()
+{
+ FUNCTIONSETUP;
+
+ TQString kpilotError;
+ TQCString kpilotDCOP;
+ int kpilotPID;
+
+ if (KApplication::startServiceByDesktopName(CSL1("kpilot"),
+ TQString::null, &kpilotError, &kpilotDCOP, &kpilotPID
+#if (KDE_VERSION >= 220)
+ // Startup notification added in 2.2
+ , ""
+#endif
+ ))
+ {
+ WARNINGKPILOT << "Couldn't start KPilot! " << kpilotError << endl;
+ }
+ else
+ {
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Started KPilot with DCOP name "
+ << kpilotDCOP << " (pid " << kpilotPID << ")" << endl;
+#endif
+ }
+}
+
+void PilotDaemon::slotRunConfig()
+{
+ FUNCTIONSETUP;
+
+ // This function tries to send the raise() DCOP call to kpilot.
+ // If it succeeds, we can assume kpilot is running and then try
+ // to send the configure() DCOP call.
+ // If it fails (probably because kpilot isn't running) it tries
+ // to call kpilot via KProcess (using a command line switch to
+ // only bring up the configure dialog).
+ //
+ // Implementing the function this way catches all cases.
+ // ie 1 KPilot running with configure dialog open (raise())
+ // 2 KPilot running with dialog NOT open (configureConduits())
+ // 3 KPilot NOT running (KProcess)
+
+ DCOPClient *client = kapp->dcopClient();
+
+ // This DCOP call to kpilot's raise function solves the final case
+ // ie when kpilot already has the dialog open
+
+ if ( client->isApplicationRegistered( "kpilot" ) )
+ {
+ client->send("kpilot", "kpilot-mainwindow#1", "raise()",TQString::null);
+ client->send("kpilot", "KPilotIface", "configure()", TQString::null);
+ }
+ else
+ {
+ // KPilot not running
+ KProcess *p = new KProcess;
+ *p << "kpilot" << "-s";
+
+ p->start();
+ }
+}
+
+void PilotDaemon::updateTrayStatus(const TQString &s)
+{
+ if (!fTray) return;
+
+ TQString tipText = CSL1("<qt>");
+ tipText.append( s );
+ tipText.append( CSL1(" ") );
+ tipText.append( i18n("Next sync is %1.")
+ .arg( fNextSyncType.name() ) );
+ tipText.append( CSL1("</qt>") );
+
+ TQToolTip::remove(fTray);
+ TQToolTip::add(fTray,tipText);
+ emitDCOPSignal( "kpilotDaemonStatusChanged()", TQByteArray() );
+ // emit the same dcop signal but including the information needed by Kontact to update its kpilot summary widget
+ TQByteArray data;
+ TQDataStream arg(data, IO_WriteOnly);
+ arg << lastSyncDate();
+ arg << shorStatusString();
+ arg << configuredConduitList();
+ arg << logFileName();
+ arg << userName();
+ arg << pilotDevice();
+ arg << killDaemonOnExit();
+ emitDCOPSignal( "kpilotDaemonStatusDetails(TQDateTime,TQString,TQStringList,TQString,TQString,TQString,bool)", data );
+}
+
+static KCmdLineOptions daemonoptions[] = {
+#ifdef DEBUG
+ {"debug <level>", I18N_NOOP("Set debugging level"), "0"},
+#endif
+ { "device <device>", I18N_NOOP("Device to try first"), ""},
+ {"fail-silently", I18N_NOOP("Exit instead of complaining about bad configuration files"), 0},
+ KCmdLineLastOption
+} ;
+
+
+int main(int argc, char **argv)
+{
+ FUNCTIONSETUP;
+
+ KLocale::setMainCatalogue("kpilot");
+
+ KAboutData about("kpilotDaemon",
+ I18N_NOOP("KPilot Daemon"),
+ KPILOT_VERSION,
+ "KPilot - HotSync software for KDE\n\n",
+ KAboutData::License_GPL,
+ "(c) 1998-2000,2001, Dan Pilone (c) 2000-2004, Adriaan de Groot",
+ 0L,
+ "http://www.kpilot.org/"
+ );
+ about.addAuthor("Dan Pilone",
+ I18N_NOOP("Project Leader"),
+ "pilone@slac.com");
+ about.addAuthor("Adriaan de Groot",
+ I18N_NOOP("Maintainer"),
+ "groot@kde.org", "http://www.kpilot.org/");
+ about.addAuthor("Reinhold Kainhofer",
+ I18N_NOOP("Developer"),
+ "reinhold@kainhofer.com", "http://reinhold.kainhofer.com/Linux/");
+ aboutData = &about;
+
+
+ KCmdLineArgs::init(argc, argv, &about);
+ KCmdLineArgs::addCmdLineOptions(daemonoptions,"kpilotconfig");
+ KUniqueApplication::addCmdLineOptions();
+ KCmdLineArgs *p = KCmdLineArgs::parsedArgs();
+
+#ifdef DEBUG
+ KPilotConfig::getDebugLevel(p);
+#endif
+ if (!KUniqueApplication::start())
+ {
+ if (p->isSet("device")){
+ // tell the running kpilotDaemon to use
+ // this device now
+ DCOPClient d;
+ TQString dev(p->getOption("device"));
+ TQByteArray data;
+ TQDataStream arg(data, IO_WriteOnly);
+ arg << dev;
+ if (d.attach()){
+ d.send("kpilotDaemon", "KPilotDaemonIface", "setTempDevice(TQString)", data );
+ d.detach();
+ }
+ }
+ return 0;
+ }
+ KUniqueApplication a(true, true);
+
+ // A block just to keep variables local.
+ //
+ //
+ {
+// KPilotSettings::self()->config()->setReadOnly(false);
+
+ if (KPilotSettings::configVersion() < KPilotConfig::ConfigurationVersion)
+ {
+ WARNINGKPILOT << "Is still not configured for use."
+ << endl;
+ if (!p->isSet("fail-silently"))
+ {
+ KPilotConfig::sorryVersionOutdated(KPilotSettings::configVersion());
+ }
+ return 1;
+ }
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Configuration version "
+ << KPilotSettings::configVersion() << endl;
+#endif
+ }
+
+
+ PilotDaemon *gPilotDaemon = new PilotDaemon();
+
+ if (p->isSet("device"))
+ gPilotDaemon->setTempDevice(p->getOption("device"));
+
+ if (gPilotDaemon->status() == PilotDaemon::ERROR)
+ {
+ delete gPilotDaemon;
+
+ gPilotDaemon = 0;
+ WARNINGKPILOT << "Failed to start up daemon "
+ "due to errors constructing it." << endl;
+ return 2;
+ }
+
+ gPilotDaemon->showTray();
+
+ return a.exec();
+}
+
+
+