00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "options.h"
00033
00034 #include <stdlib.h>
00035
00036 #include <qtimer.h>
00037 #include <qtooltip.h>
00038 #include <qpixmap.h>
00039
00040 #include <kuniqueapplication.h>
00041 #include <kaboutapplication.h>
00042 #include <kcmdlineargs.h>
00043 #include <kwin.h>
00044 #include <kurl.h>
00045 #include <kpopupmenu.h>
00046 #include <kiconloader.h>
00047 #include <kdebug.h>
00048 #include <kprocess.h>
00049 #include <dcopclient.h>
00050 #include <kurldrag.h>
00051 #include <kservice.h>
00052 #include <kapplication.h>
00053 #include <khelpmenu.h>
00054
00055 #include "pilotRecord.h"
00056
00057 #include "fileInstaller.h"
00058 #include "pilotUser.h"
00059 #include "pilotDatabase.h"
00060 #include "kpilotlink.h"
00061 #include "kpilotdevicelink.h"
00062
00063 #include "hotSync.h"
00064 #include "interactiveSync.h"
00065 #include "syncStack.h"
00066 #include "internalEditorAction.h"
00067 #include "logFile.h"
00068
00069 #include "kpilotConfig.h"
00070
00071
00072 #include "kpilotDCOP_stub.h"
00073 #include "kpilotDCOP.h"
00074 #include "loggerDCOP_stub.h"
00075
00076 #include "pilotDaemon.moc"
00077
00078 static KAboutData *aboutData = 0L;
00079
00080 PilotDaemonTray::PilotDaemonTray(PilotDaemon * p) :
00081 KSystemTray(0, "pilotDaemon"),
00082 fSyncTypeMenu(0L),
00083 daemon(p),
00084 kap(0L),
00085 fBlinkTimer(0L)
00086 {
00087 FUNCTIONSETUP;
00088 setupWidget();
00089 setAcceptDrops(true);
00090 }
00091
00092 void PilotDaemonTray::dragEnterEvent(QDragEnterEvent * e)
00093 {
00094 FUNCTIONSETUP;
00095 e->accept(KURLDrag::canDecode(e));
00096 }
00097
00098 void PilotDaemonTray::dropEvent(QDropEvent * e)
00099 {
00100 FUNCTIONSETUP;
00101
00102 KURL::List list;
00103
00104 KURLDrag::decode(e, list);
00105
00106 QStringList files;
00107 for(KURL::List::ConstIterator it = list.begin(); it != list.end(); ++it)
00108 {
00109 if ((*it).isLocalFile())
00110 files << (*it).path();
00111 }
00112
00113 daemon->addInstallFiles(files);
00114 }
00115
00116 void PilotDaemonTray::mousePressEvent(QMouseEvent * e)
00117 {
00118 FUNCTIONSETUP;
00119
00120 switch (e->button())
00121 {
00122 case RightButton:
00123 {
00124 KPopupMenu *menu = contextMenu();
00125 contextMenuAboutToShow(menu);
00126 menu->popup(e->globalPos());
00127 }
00128 break;
00129 case LeftButton:
00130 if (daemon) daemon->slotRunKPilot();
00131 break;
00132 default:
00133 KSystemTray::mousePressEvent(e);
00134 }
00135 }
00136
00137 void PilotDaemonTray::closeEvent(QCloseEvent *)
00138 {
00139 FUNCTIONSETUP;
00140 daemon->quitNow();
00141 }
00142
00143 void PilotDaemonTray::setupWidget()
00144 {
00145 FUNCTIONSETUP;
00146
00147 KGlobal::iconLoader()->addAppDir( CSL1("kpilot") );
00148 icons[Normal] = loadIcon( CSL1("kpilotDaemon") );
00149 icons[Busy] = loadIcon( CSL1("busysync") );
00150 icons[NotListening] = loadIcon( CSL1("nosync") );
00151
00152 slotShowNotListening();
00153 QTimer::singleShot(2000,this,SLOT(slotShowNormal()));
00154
00155 KPopupMenu *menu = contextMenu();
00156
00157 menuKPilotItem = menu->insertItem(i18n("Start &KPilot"), daemon,
00158 SLOT(slotRunKPilot()));
00159 menuConfigureConduitsItem = menu->insertItem(i18n("&Configure KPilot..."),
00160 daemon, SLOT(slotRunConfig()));
00161 menu->insertSeparator();
00162
00163 fSyncTypeMenu = new KPopupMenu(menu,"sync_type_menu");
00164 QString once = i18n("Appended to names of sync types to indicate the sync will happen just one time"," (once)");
00165 #define MI(a) fSyncTypeMenu->insertItem( \
00166 SyncAction::SyncMode::name(SyncAction::SyncMode::a) + once, \
00167 (int)(SyncAction::SyncMode::a));
00168 fSyncTypeMenu->insertItem(i18n("Default (%1)")
00169 .arg(SyncAction::SyncMode::name((SyncAction::SyncMode::Mode)KPilotSettings::syncType())),
00170 0);
00171 fSyncTypeMenu->insertSeparator();
00172
00173
00174 MI(eHotSync);
00175 MI(eFullSync);
00176 MI(eBackup);
00177 MI(eRestore);
00178 MI(eCopyHHToPC);
00179 MI(eCopyPCToHH);
00180
00181 fSyncTypeMenu->setCheckable(true);
00182 fSyncTypeMenu->setItemChecked(0,true);
00183 #undef MI
00184 connect(fSyncTypeMenu,SIGNAL(activated(int)),daemon,SLOT(requestSync(int)));
00185 menu->insertItem(i18n("Next &Sync"),fSyncTypeMenu);
00186
00187 KHelpMenu *help = new KHelpMenu(menu,aboutData);
00188 menu->insertItem(
00189 KGlobal::iconLoader()->loadIconSet(CSL1("help"),KIcon::Small,0,true),
00190 i18n("&Help"),help->menu(),false );
00191
00192
00193
00194 #ifdef DEBUG
00195 DEBUGKPILOT << fname << ": Finished getting icons" << endl;
00196 #endif
00197 }
00198
00199 void PilotDaemonTray::slotShowAbout()
00200 {
00201 FUNCTIONSETUP;
00202
00203 if (!kap)
00204 {
00205 kap = new KAboutApplication(0, "kpdab", false);
00206 }
00207
00208 kap->show();
00209 }
00210
00211
00212 void PilotDaemonTray::enableRunKPilot(bool b)
00213 {
00214 FUNCTIONSETUP;
00215 contextMenu()->setItemEnabled(menuKPilotItem, b);
00216 contextMenu()->setItemEnabled(menuConfigureConduitsItem, b);
00217 }
00218
00219
00220 void PilotDaemonTray::changeIcon(IconShape i)
00221 {
00222 FUNCTIONSETUP;
00223 if (icons[i].isNull())
00224 {
00225 kdWarning() << k_funcinfo
00226 << ": Icon #"<<i<<" is NULL!" << endl;
00227 }
00228 setPixmap(icons[i]);
00229 fCurrentIcon = i;
00230 }
00231
00232 void PilotDaemonTray::slotShowNormal()
00233 {
00234 FUNCTIONSETUP;
00235 changeIcon(Normal);
00236 }
00237
00238 void PilotDaemonTray::slotShowBusy()
00239 {
00240 FUNCTIONSETUP;
00241 changeIcon(Busy);
00242 }
00243
00244 void PilotDaemonTray::slotShowNotListening()
00245 {
00246 FUNCTIONSETUP;
00247 changeIcon( NotListening );
00248 }
00249
00250 void PilotDaemonTray::slotBusyTimer()
00251 {
00252 if (fCurrentIcon == Busy) changeIcon(Normal);
00253 else if (fCurrentIcon == Normal) changeIcon(Busy);
00254 }
00255
00256 void PilotDaemonTray::startHotSync()
00257 {
00258 changeIcon(Busy);
00259 if (!fBlinkTimer)
00260 {
00261 fBlinkTimer = new QTimer(this,"blink timer");
00262 }
00263 if (fBlinkTimer)
00264 {
00265 connect(fBlinkTimer,SIGNAL(timeout()),
00266 this,SLOT(slotBusyTimer()));
00267 fBlinkTimer->start(350,false);
00268 }
00269 }
00270
00271 void PilotDaemonTray::endHotSync()
00272 {
00273 changeIcon(Normal);
00274 if (fBlinkTimer)
00275 {
00276 fBlinkTimer->stop();
00277 }
00278 }
00279
00280
00281 PilotDaemon::PilotDaemon() :
00282 DCOPObject("KPilotDaemonIface"),
00283 fDaemonStatus(INIT),
00284 fPostSyncAction(None),
00285 fPilotLink(0L),
00286 fNextSyncType(SyncAction::SyncMode::eHotSync,true),
00287 fSyncStack(0L),
00288 fTray(0L),
00289 fInstaller(0L),
00290 fLogFile(0L),
00291 fLogStub(new LoggerDCOP_stub("kpilot", "LogIface")),
00292 fLogFileStub(new LoggerDCOP_stub("kpilotDaemon", "LogIface")),
00293 fKPilotStub(new KPilotDCOP_stub("kpilot", "KPilotIface")),
00294 fTempDevice(QString::null)
00295 {
00296 FUNCTIONSETUP;
00297
00298 setupPilotLink();
00299 reloadSettings();
00300
00301 if (fDaemonStatus == ERROR)
00302 {
00303 kdWarning() << k_funcinfo
00304 << ": Connecting to device failed." << endl;
00305 return;
00306 }
00307
00308 fInstaller = new FileInstaller;
00309 fLogFile = new LogFile;
00310 connect(fInstaller, SIGNAL(filesChanged()),
00311 this, SLOT(slotFilesChanged()));
00312
00313 fNextSyncType.setMode( KPilotSettings::syncType() );
00314
00315 #ifdef DEBUG
00316 DEBUGKPILOT << fname
00317 << ": The daemon is ready with status "
00318 << statusString() << " (" << (int) fDaemonStatus << ")" << endl;
00319 #endif
00320 }
00321
00322 PilotDaemon::~PilotDaemon()
00323 {
00324 FUNCTIONSETUP;
00325
00326 KPILOT_DELETE(fPilotLink);
00327 KPILOT_DELETE(fSyncStack);
00328 KPILOT_DELETE(fInstaller);
00329
00330 (void) PilotDatabase::count();
00331 }
00332
00333 void PilotDaemon::addInstallFiles(const QStringList &l)
00334 {
00335 FUNCTIONSETUP;
00336
00337 fInstaller->addFiles( l, fTray );
00338 }
00339
00340 int PilotDaemon::getPilotSpeed()
00341 {
00342 FUNCTIONSETUP;
00343
00344 int speed = KPilotSettings::pilotSpeed();
00345
00346
00347
00348
00349
00350
00351 const char *speedname = 0L;
00352
00353 switch (speed)
00354 {
00355 case 0:
00356 speedname = "PILOTRATE=9600";
00357 break;
00358 case 1:
00359 speedname = "PILOTRATE=19200";
00360 break;
00361 case 2:
00362 speedname = "PILOTRATE=38400";
00363 break;
00364 case 3:
00365 speedname = "PILOTRATE=57600";
00366 break;
00367 case 4:
00368 speedname = "PILOTRATE=115200";
00369 break;
00370 default:
00371 speedname = "PILOTRATE=9600";
00372 }
00373
00374 #ifdef DEBUG
00375 DEBUGKPILOT << fname
00376 << ": Speed set to "
00377 << speedname << " (" << speed << ")" << endl;
00378 #endif
00379
00380 putenv((char *) speedname);
00381
00382 return speed;
00383 }
00384
00385
00386 void PilotDaemon::showTray()
00387 {
00388 FUNCTIONSETUP;
00389
00390 if (!fTray)
00391 {
00392 #ifdef DEBUG
00393 DEBUGKPILOT << fname << ": No tray icon to display!" << endl;
00394 #endif
00395
00396 return;
00397 }
00398
00399
00400 KWin::setSystemTrayWindowFor(fTray->winId(), 0);
00401 fTray->setGeometry(-100, -100, 42, 42);
00402 fTray->show();
00403
00404 #ifdef DEBUG
00405 DEBUGKPILOT << fname << ": Tray icon displayed." << endl;
00406 #endif
00407
00408 updateTrayStatus();
00409 }
00410
00411 void PilotDaemon::setTempDevice(QString d)
00412 {
00413 if ( !d.isEmpty() ){
00414 fTempDevice = d;
00415 if (fPilotLink)
00416 fPilotLink->setTempDevice( fTempDevice );
00417 reloadSettings();
00418 }
00419 }
00420
00421 void PilotDaemon::reloadSettings()
00422 {
00423 FUNCTIONSETUP;
00424
00425 switch (fDaemonStatus)
00426 {
00427 case INIT:
00428 case HOTSYNC_END:
00429 case ERROR:
00430 case READY:
00431 case NOT_LISTENING:
00432
00433 break;
00434 case HOTSYNC_START:
00435 case FILE_INSTALL_REQ:
00436
00437 fPostSyncAction |= ReloadSettings;
00438 return;
00439 break;
00440 }
00441
00442
00443 delete KPilotSettings::self();
00444 KPilotSettings::self()->config()->reparseConfiguration();
00445 KPilotSettings::self()->readConfig();
00446 getPilotSpeed();
00447
00448 (void) Pilot::setupPilotCodec(KPilotSettings::encoding());
00449 (void) Pilot::setupPilotCodec(KPilotSettings::encoding());
00450
00451 #ifdef DEBUG
00452 DEBUGKPILOT << fname
00453 << ": Got configuration "
00454 << KPilotSettings::pilotDevice()
00455 << endl;
00456 DEBUGKPILOT << fname
00457 << ": Got conduit list "
00458 << (KPilotSettings::installedConduits().join(CSL1(",")))
00459 << endl;
00460 #endif
00461
00462 requestSync(0);
00463
00464
00465 if (fPilotLink)
00466 {
00467 #ifdef DEBUG
00468 DEBUGKPILOT << fname
00469 << ": Resetting with device "
00470 << KPilotSettings::pilotDevice()
00471 << endl;
00472 #endif
00473
00474 fPilotLink->reset( KPilotSettings::pilotDevice() );
00475 #ifdef DEBUG
00476 DEBUGKPILOT << fname
00477 << ": Using workarounds "
00478 << KPilotSettings::workarounds()
00479 << endl;
00480 #endif
00481 if ( KPilotSettings::workarounds() == KPilotSettings::eWorkaroundUSB )
00482 {
00483 #ifdef DEBUG
00484 DEBUGKPILOT << fname
00485 << ": Using Zire31 USB workaround." << endl;
00486 #endif
00487 fPilotLink->setWorkarounds(true);
00488 }
00489 }
00490
00491 if (KPilotSettings::dockDaemon())
00492 {
00493 if (!fTray)
00494 {
00495 fTray = new PilotDaemonTray(this);
00496 fTray->show();
00497 }
00498 else
00499 {
00500 fTray->show();
00501 }
00502 }
00503 else
00504 {
00505 if (fTray)
00506 {
00507 fTray->hide();
00508 delete fTray;
00509
00510 fTray = 0L;
00511 }
00512 }
00513
00514 updateTrayStatus();
00515 logProgress(QString::null,0);
00516 }
00517
00518 void PilotDaemon::stopListening()
00519 {
00520 fIsListening=false;
00521 fTray->changeIcon(PilotDaemonTray::NotListening);
00522 fDaemonStatus=NOT_LISTENING;
00523 fPilotLink->close();
00524 }
00525
00526 void PilotDaemon::startListening()
00527 {
00528 fIsListening=true;
00529 fTray->changeIcon(PilotDaemonTray::Normal);
00530 fDaemonStatus=INIT;
00531 fPilotLink->reset();
00532 }
00533
00534 QString PilotDaemon::statusString()
00535 {
00536 FUNCTIONSETUP;
00537
00538 QString s = CSL1("PilotDaemon=");
00539 s.append(shortStatusString());
00540
00541 s.append(CSL1("; NextSync="));
00542 s.append(fNextSyncType.name());
00543
00544 s.append(CSL1(" ("));
00545 if (fPilotLink)
00546 {
00547 s.append(fPilotLink->statusString());
00548 }
00549 s.append(CSL1(");"));
00550
00551 return s;
00552 }
00553
00554 QString PilotDaemon::shortStatusString()
00555 {
00556 FUNCTIONSETUP;
00557
00558 QString s;
00559
00560 switch (status())
00561 {
00562 case INIT:
00563 s.append(CSL1("Waiting for sync"));
00564 break;
00565 case READY:
00566 s.append(CSL1("Listening on device"));
00567 break;
00568 case ERROR:
00569 s=CSL1("Error");
00570 break;
00571 case FILE_INSTALL_REQ:
00572 s=CSL1("Installing File");
00573 break;
00574 case HOTSYNC_END:
00575 s=CSL1("End of Hotsync");
00576 break;
00577 case HOTSYNC_START:
00578 s=CSL1("Syncing");
00579 break;
00580 case NOT_LISTENING:
00581 s.append(CSL1("Not Listening (stopped manually)"));
00582 break;
00583 }
00584
00585 return s;
00586 }
00587
00588
00589
00590 bool PilotDaemon::setupPilotLink()
00591 {
00592 FUNCTIONSETUP;
00593
00594 KPILOT_DELETE(fPilotLink);
00595 fPilotLink = new KPilotDeviceLink( 0, 0, fTempDevice );
00596 if (!fPilotLink)
00597 {
00598 kdWarning() << k_funcinfo
00599 << ": Can't get pilot link." << endl;
00600 return false;
00601 }
00602
00603 QObject::connect(fPilotLink, SIGNAL(deviceReady(KPilotLink*)),
00604 this, SLOT(startHotSync(KPilotLink*)));
00605
00606 QObject::connect(fPilotLink, SIGNAL(logError(const QString &)),
00607 this, SLOT(logError(const QString &)));
00608 QObject::connect(fPilotLink, SIGNAL(logMessage(const QString &)),
00609 this, SLOT(logMessage(const QString &)));
00610 QObject::connect(fPilotLink,
00611 SIGNAL(logProgress(const QString &,int)),
00612 this, SLOT(logProgress(const QString &,int)));
00613
00614
00615 return true;
00616 }
00617
00618
00619 void PilotDaemon::quitNow()
00620 {
00621 FUNCTIONSETUP;
00622
00623
00624
00625 switch (fDaemonStatus)
00626 {
00627 case INIT:
00628 case HOTSYNC_END:
00629 case ERROR:
00630 case NOT_LISTENING:
00631 getKPilot().daemonStatus(KPilotDCOP::DaemonQuit);
00632 kapp->quit();
00633 break;
00634 case READY:
00635 case HOTSYNC_START:
00636 case FILE_INSTALL_REQ:
00637 fPostSyncAction |= Quit;
00638 break;
00639 }
00640 emitDCOPSignal( "kpilotDaemonStatusChanged()", QByteArray() );
00641 }
00642
00643 void PilotDaemon::requestRegularSyncNext()
00644 {
00645 requestSync(SyncAction::SyncMode::eHotSync);
00646 }
00647
00648
00649 void PilotDaemon::requestSync(int mode)
00650 {
00651 FUNCTIONSETUP;
00652
00653 if ( 0==mode )
00654 {
00655 mode = KPilotSettings::syncType();
00656 }
00657
00658 if ( !fNextSyncType.setMode(mode) )
00659 {
00660 kdWarning() << k_funcinfo << ": Ignored fake sync type " << mode << endl;
00661 return;
00662 }
00663
00664 updateTrayStatus();
00665
00666 if (fTray && (fTray->fSyncTypeMenu))
00667 {
00668 for (int i=((int)SyncAction::SyncMode::eHotSync);
00669 i<=((int)SyncAction::SyncMode::eRestore) ;
00670 ++i)
00671 {
00672 fTray->fSyncTypeMenu->setItemChecked(i,mode==i);
00673 }
00674 }
00675
00676 getLogger().logMessage(i18n("Next HotSync will be: %1. ").arg(fNextSyncType.name()) +
00677 i18n("Please press the HotSync button."));
00678 }
00679
00680 void PilotDaemon::requestSyncType(QString s)
00681 {
00682 FUNCTIONSETUP;
00683
00684
00685 if (s.startsWith(CSL1("H"))) requestSync(SyncAction::SyncMode::eHotSync);
00686 else if (s.startsWith(CSL1("Fu"))) requestSync(SyncAction::SyncMode::eFullSync);
00687 else if (s.startsWith(CSL1("B"))) requestSync(SyncAction::SyncMode::eBackup);
00688 else if (s.startsWith(CSL1("R"))) requestSync(SyncAction::SyncMode::eRestore);
00689 else if (s.startsWith(CSL1("T"))) { fNextSyncType.setOptions(true,false); }
00690 else if (s.startsWith(CSL1("CopyHHToPC"))) requestSync(SyncAction::SyncMode::eCopyHHToPC);
00691 else if (s.startsWith(CSL1("CopyPCToHH"))) requestSync(SyncAction::SyncMode::eCopyPCToHH);
00692 else if (s.startsWith(CSL1("D"))) requestSync(0);
00693 else
00694 {
00695 kdWarning() << ": Unknown sync type " << ( s.isEmpty() ? CSL1("<none>") : s )
00696 << endl;
00697 }
00698 }
00699
00700 void PilotDaemon::requestSyncOptions(bool test, bool local)
00701 {
00702 if ( !fNextSyncType.setOptions(test,local) )
00703 {
00704 kdWarning() << k_funcinfo << ": Nonsensical request for "
00705 << (test ? "test" : "notest")
00706 << ' '
00707 << (local ? "local" : "nolocal")
00708 << " in mode "
00709 << fNextSyncType.name() << endl;
00710 }
00711 }
00712
00713 int PilotDaemon::nextSyncType() const
00714 {
00715 return fNextSyncType.mode();
00716 }
00717
00721 QDateTime PilotDaemon::lastSyncDate()
00722 {
00723 return KPilotSettings::lastSyncTime();
00724 }
00725
00726
00727 static QDict<QString> *conduitNameMap = 0L;
00728
00729 static void fillConduitNameMap()
00730 {
00731 if ( !conduitNameMap )
00732 {
00733 conduitNameMap = new QDict<QString>;
00734 conduitNameMap->setAutoDelete(true);
00735 }
00736 conduitNameMap->clear();
00737
00738 QStringList l = KPilotSettings::installedConduits();
00739
00740 if ( l.find( CSL1("internal_fileinstall") ) != l.end() ) {
00741 conduitNameMap->insert( CSL1("internal_fileinstall"),
00742 new QString(i18n("File Installer")) );
00743 }
00744
00745 QStringList::ConstIterator end = l.end();
00746 for (QStringList::ConstIterator i = l.begin(); i != end; ++i)
00747 {
00748 if (!conduitNameMap->find(*i))
00749 {
00750 QString readableName = CSL1("<unknown>");
00751 KSharedPtr < KService > o = KService::serviceByDesktopName(*i);
00752 if (!o)
00753 {
00754 kdWarning() << k_funcinfo << ": No service for " << *i << endl;
00755 }
00756 else
00757 {
00758 readableName = o->name();
00759 }
00760 conduitNameMap->insert( *i, new QString(readableName) );
00761 }
00762 }
00763 }
00764
00765
00766 QStringList PilotDaemon::configuredConduitList()
00767 {
00768 fillConduitNameMap();
00769
00770 QStringList keys;
00771
00772 QDictIterator<QString> it(*conduitNameMap);
00773 for ( ; *it; ++it)
00774 {
00775 keys << it.currentKey();
00776 }
00777 keys.sort();
00778
00779 QStringList::ConstIterator end = keys.end();
00780 QStringList result;
00781 for (QStringList::ConstIterator i = keys.begin(); i != end; ++i)
00782 {
00783 result << *(conduitNameMap->find(*i));
00784 }
00785
00786 return result;
00787 }
00788
00789 QString PilotDaemon::logFileName()
00790 {
00791 return KPilotSettings::logFileName();
00792 }
00793
00794 QString PilotDaemon::userName()
00795 {
00796 return KPilotSettings::userName();
00797 }
00798 QString PilotDaemon::pilotDevice()
00799 {
00800 return KPilotSettings::pilotDevice();
00801 }
00802
00803 bool PilotDaemon::killDaemonOnExit()
00804 {
00805 return KPilotSettings::killDaemonAtExit();
00806 }
00807
00808 typedef enum { NotLocked=0, Locked=1, DCOPError=2 } KDesktopLockStatus;
00809 static KDesktopLockStatus isKDesktopLockRunning()
00810 {
00811 if (!KPilotSettings::screenlockSecure()) return NotLocked;
00812
00813 DCOPClient *dcopptr = KApplication::kApplication()->dcopClient();
00814
00815
00816 if (!dcopptr || !dcopptr->isAttached())
00817 {
00818 kdWarning() << k_funcinfo << ": Could not make DCOP connection. "
00819 << "Assuming screensaver is active." << endl;
00820 return DCOPError;
00821 }
00822
00823 QByteArray data,returnValue;
00824 QCString returnType;
00825
00826 if (!dcopptr->call("kdesktop","KScreensaverIface","isBlanked()",
00827 data,returnType,returnValue,true))
00828 {
00829 kdWarning() << k_funcinfo << ": Check for screensaver failed."
00830 << "Assuming screensaver is active." << endl;
00831
00832 return DCOPError;
00833 }
00834
00835 if (returnType == "bool")
00836 {
00837 bool b;
00838 QDataStream reply(returnValue,IO_ReadOnly);
00839 reply >> b;
00840 return (b ? Locked : NotLocked);
00841 }
00842 else
00843 {
00844 kdWarning() << k_funcinfo << ": Strange return value from screensaver. "
00845 << "Assuming screensaver is active." << endl;
00846
00847 return DCOPError;
00848 }
00849 }
00850
00851
00852 static void informOthers(KPilotDCOP_stub &kpilot,
00853 LoggerDCOP_stub &log,
00854 LoggerDCOP_stub &filelog)
00855 {
00856 kpilot.daemonStatus(KPilotDCOP::StartOfHotSync);
00857 log.logStartSync();
00858 filelog.logStartSync();
00859 }
00860
00861 static bool isSyncPossible(ActionQueue *fSyncStack,
00862 KPilotLink *pilotLink,
00863 KPilotDCOP_stub &kpilot)
00864 {
00865 FUNCTIONSETUP;
00866
00873 int kpilotstatus = kpilot.kpilotStatus();
00874 DCOPStub::Status callstatus = kpilot.status();
00875
00876 #ifdef DEBUG
00877 if (callstatus != DCOPStub::CallSucceeded)
00878 {
00879 DEBUGKPILOT << fname <<
00880 ": Could not call KPilot for status." << endl;
00881 }
00882 else
00883 {
00884 DEBUGKPILOT << fname << ": KPilot status " << kpilotstatus << endl;
00885 }
00886 #endif
00887
00891 if ((callstatus == DCOPStub::CallSucceeded) &&
00892 (kpilotstatus != KPilotDCOP::WaitingForDaemon))
00893 {
00894 kdWarning() << k_funcinfo <<
00895 ": KPilot returned status " << kpilotstatus << endl;
00896
00897 fSyncStack->queueInit();
00898 fSyncStack->addAction(new SorryAction(pilotLink));
00899 return false;
00900 }
00901
00902 switch (isKDesktopLockRunning())
00903 {
00904 case NotLocked :
00905 break;
00906 case Locked :
00907 fSyncStack->queueInit();
00908 fSyncStack->addAction(new SorryAction(pilotLink,
00909 i18n("HotSync is disabled while the screen is locked.")));
00910 return false;
00911 case DCOPError :
00912 fSyncStack->queueInit();
00913 fSyncStack->addAction(new SorryAction(pilotLink,
00914 i18n("HotSync is disabled because KPilot could not "
00915 "determine the state of the screen saver. You "
00916 "can disable this security feature by unchecking "
00917 "the 'do not sync when screensaver is active' box "
00918 "in the HotSync page of the configuration dialog.")));
00919 return false;
00920 }
00921
00922 return true;
00923 }
00924
00925 static void queueInstaller(ActionQueue *fSyncStack,
00926 FileInstaller *fInstaller,
00927 const QStringList &c)
00928 {
00929 if (c.findIndex(CSL1("internal_fileinstall")) >= 0)
00930 {
00931 fSyncStack->queueInstaller(fInstaller->dir());
00932 }
00933 }
00934
00935 static void queueEditors(ActionQueue *fSyncStack, KPilotLink *pilotLink)
00936 {
00937 if (KPilotSettings::internalEditors())
00938 {
00939 fSyncStack->addAction(new InternalEditorAction(pilotLink));
00940 }
00941 }
00942
00943 static void queueConduits(ActionQueue *fSyncStack,
00944 const QStringList &conduits,
00945 SyncAction::SyncMode e)
00946 {
00947 if (conduits.count() > 0)
00948 {
00949 fSyncStack->queueConduits( conduits,e);
00950
00951
00952
00953 }
00954 }
00955
00956 bool PilotDaemon::shouldBackup()
00957 {
00958
00959 FUNCTIONSETUP;
00960
00961 bool ret = false;
00962 int backupfreq = KPilotSettings::backupFrequency();
00963
00964 #ifdef DEBUG
00965 DEBUGKPILOT << fname << ": Backup Frequency is: [" << backupfreq <<
00966 "]. " << endl;
00967 #endif
00968
00969 if ( (fNextSyncType == SyncAction::SyncMode::eHotSync) ||
00970 (fNextSyncType == SyncAction::SyncMode::eFullSync) )
00971 {
00975 if ( backupfreq == SyncAction::eOnRequestOnly )
00976 {
00977 #ifdef DEBUG
00978 DEBUGKPILOT << fname << ": Should not do backup..." << endl;
00979 #endif
00980 ret = false;
00981 }
00982 else if ( backupfreq == SyncAction::eEveryHotSync )
00983 {
00984 #ifdef DEBUG
00985 DEBUGKPILOT << fname << ": Should do backup..." << endl;
00986 #endif
00987 ret = true;
00988 }
00989 }
00990
00991 return ret;
00992
00993 }
00994
00995
00996 void PilotDaemon::startHotSync(KPilotLink *pilotLink)
00997 {
00998 FUNCTIONSETUP;
00999
01000 bool pcchanged=false;
01001 QStringList conduits ;
01002 QString s;
01003
01004 #ifdef DEBUG
01005 DEBUGKPILOT << fname
01006 << ": Starting Sync with type "
01007 << fNextSyncType.name() << endl;
01008 DEBUGKPILOT << fname << ": Status is " << shortStatusString() << endl;
01009 (void) PilotDatabase::count();
01010 #endif
01011
01012 fDaemonStatus = HOTSYNC_START ;
01013 if (fTray)
01014 {
01015 fTray->startHotSync();
01016 }
01017 informOthers(getKPilot(),getLogger(),getFileLogger());
01018
01019
01020
01021 fSyncStack = new ActionQueue(pilotLink);
01022
01023
01024 if (!isSyncPossible(fSyncStack,pilotLink,getKPilot()))
01025 {
01026
01027
01028 goto launch;
01029 }
01030
01031
01032
01033
01034 if (fNextSyncType.mode() != SyncAction::SyncMode::eRestore)
01035 {
01036
01037 KPilotUser &usr = pilotLink->getPilotUser();
01038 pcchanged = usr.getLastSyncPC() !=(unsigned long) gethostid();
01039
01040 if (pcchanged)
01041 {
01042 #ifdef DEBUG
01043 DEBUGKPILOT << fname << ": PC changed. Last sync PC: [" << usr.getLastSyncPC()
01044 << "], me: [" << (unsigned long) gethostid() << "]" << endl;
01045 #endif
01046 if ( KPilotSettings::fullSyncOnPCChange() )
01047 {
01048 #ifdef DEBUG
01049 DEBUGKPILOT << fname << ": Setting sync mode to full sync. " << endl;
01050 #endif
01051 fNextSyncType = SyncAction::SyncMode::eFullSync;
01052 }
01053 else
01054 {
01055 #ifdef DEBUG
01056 DEBUGKPILOT << fname << ": Not changing sync mode because of settings. " << endl;
01057 #endif
01058 }
01059 }
01060 }
01061
01062
01063 fSyncStack->queueInit( ActionQueue::queueCheckUser );
01064
01065 conduits = KPilotSettings::installedConduits() ;
01066
01067 if (fNextSyncType.isTest())
01068 {
01069 fSyncStack->addAction(new TestLink(pilotLink));
01070 }
01071 else
01072 {
01073 switch (fNextSyncType.mode())
01074 {
01075 case SyncAction::SyncMode::eBackup:
01076 if (KPilotSettings::runConduitsWithBackup() && (conduits.count() > 0))
01077 {
01078 queueConduits(fSyncStack,conduits,fNextSyncType);
01079 }
01080 fSyncStack->addAction(new BackupAction(pilotLink,true));
01081 break;
01082 case SyncAction::SyncMode::eRestore:
01083 fSyncStack->addAction(new RestoreAction(pilotLink));
01084 queueInstaller(fSyncStack,fInstaller,conduits);
01085 break;
01086 case SyncAction::SyncMode::eFullSync:
01087 case SyncAction::SyncMode::eHotSync:
01088
01089
01090 queueInstaller(fSyncStack,fInstaller,conduits);
01091 queueEditors(fSyncStack,pilotLink);
01092 queueConduits(fSyncStack,conduits,fNextSyncType);
01093
01094 queueInstaller(fSyncStack,fInstaller,conduits);
01095
01096 if (shouldBackup())
01097 {
01098 fSyncStack->addAction(new BackupAction(pilotLink, (fNextSyncType == SyncAction::SyncMode::eFullSync)));
01099 }
01100 break;
01101 case SyncAction::SyncMode::eCopyPCToHH:
01102 queueConduits(fSyncStack,conduits,SyncAction::SyncMode::eCopyPCToHH);
01103 break;
01104 case SyncAction::SyncMode::eCopyHHToPC:
01105 queueConduits(fSyncStack,conduits,SyncAction::SyncMode::eCopyHHToPC);
01106 break;
01107 }
01108 }
01109
01110
01111
01112 launch:
01113 fSyncStack->queueCleanup();
01114
01115 QObject::connect(fSyncStack, SIGNAL(logError(const QString &)),
01116 this, SLOT(logError(const QString &)));
01117 QObject::connect(fSyncStack, SIGNAL(logMessage(const QString &)),
01118 this, SLOT(logMessage(const QString &)));
01119 QObject::connect(fSyncStack,
01120 SIGNAL(logProgress(const QString &,int)),
01121 this, SLOT(logProgress(const QString &,int)));
01122
01123 QObject::connect(fSyncStack, SIGNAL(syncDone(SyncAction *)),
01124 this, SLOT(endHotSync()));
01125
01126 QTimer::singleShot(0,fSyncStack,SLOT(execConduit()));
01127
01128 updateTrayStatus();
01129 }
01130
01131 void PilotDaemon::logMessage(const QString & s)
01132 {
01133 FUNCTIONSETUPL(2);
01134
01135 getLogger().logMessage(s);
01136 getFileLogger().logMessage(s);
01137 updateTrayStatus(s);
01138 }
01139
01140 void PilotDaemon::logError(const QString & s)
01141 {
01142 FUNCTIONSETUP;
01143
01144 getLogger().logError(s);
01145 getFileLogger().logError(s);
01146 updateTrayStatus(s);
01147 }
01148
01149 void PilotDaemon::logProgress(const QString & s, int i)
01150 {
01151 FUNCTIONSETUPL(2);
01152
01153 getLogger().logProgress(s, i);
01154 getFileLogger().logProgress(s, i);
01155 if (!s.isEmpty()) updateTrayStatus(s);
01156 }
01157
01158 void PilotDaemon::endHotSync()
01159 {
01160 FUNCTIONSETUP;
01161
01162 if (fTray)
01163 {
01164 fTray->endHotSync();
01165 }
01166
01167 KPILOT_DELETE(fSyncStack);
01168 fPilotLink->close();
01169
01170 getLogger().logProgress(i18n("HotSync Completed.<br>"), 100);
01171 getFileLogger().logProgress(i18n("HotSync Completed.<br>"), 100);
01172 getLogger().logEndSync();
01173 getFileLogger().logEndSync();
01174 getKPilot().daemonStatus(KPilotDCOP::EndOfHotSync);
01175 KPilotSettings::setLastSyncTime(QDateTime::currentDateTime());
01176 KPilotSettings::self()->writeConfig();
01177
01178 fDaemonStatus = HOTSYNC_END;
01179
01180 if (fPostSyncAction & Quit)
01181 {
01182 getKPilot().daemonStatus(KPilotDCOP::DaemonQuit);
01183 kapp->quit();
01184 }
01185 if (fPostSyncAction & ReloadSettings)
01186 {
01187 reloadSettings();
01188 }
01189 else
01190 {
01191 QTimer::singleShot(10000,fPilotLink,SLOT(reset()));
01192 }
01193
01194 fPostSyncAction = None;
01195 requestSync(0);
01196
01197 (void) PilotDatabase::count();
01198
01199 updateTrayStatus();
01200 }
01201
01202
01203 void PilotDaemon::slotFilesChanged()
01204 {
01205 FUNCTIONSETUP;
01206 }
01207
01208 void PilotDaemon::slotRunKPilot()
01209 {
01210 FUNCTIONSETUP;
01211
01212 QString kpilotError;
01213 QCString kpilotDCOP;
01214 int kpilotPID;
01215
01216 if (KApplication::startServiceByDesktopName(CSL1("kpilot"),
01217 QString::null, &kpilotError, &kpilotDCOP, &kpilotPID
01218 #if (KDE_VERSION >= 220)
01219
01220 , ""
01221 #endif
01222 ))
01223 {
01224 kdWarning() << k_funcinfo
01225 << ": Couldn't start KPilot! " << kpilotError << endl;
01226 }
01227 else
01228 {
01229 #ifdef DEBUG
01230 DEBUGKPILOT << fname
01231 << ": Started KPilot with DCOP name "
01232 << kpilotDCOP << " (pid " << kpilotPID << ")" << endl;
01233 #endif
01234 }
01235 }
01236
01237 void PilotDaemon::slotRunConfig()
01238 {
01239 FUNCTIONSETUP;
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 DCOPClient *client = kapp->dcopClient();
01254
01255
01256
01257
01258 if ( client->isApplicationRegistered( "kpilot" ) )
01259 {
01260 client->send("kpilot", "kpilot-mainwindow#1", "raise()",QString::null);
01261 client->send("kpilot", "KPilotIface", "configure()", QString::null);
01262 }
01263 else
01264 {
01265
01266 KProcess *p = new KProcess;
01267 *p << "kpilot" << "-s";
01268
01269 p->start();
01270 }
01271 }
01272
01273 void PilotDaemon::updateTrayStatus(const QString &s)
01274 {
01275 if (!fTray) return;
01276
01277 QString tipText = CSL1("<qt>");
01278 tipText.append( s );
01279 tipText.append( CSL1(" ") );
01280 tipText.append( i18n("Next sync is %1.")
01281 .arg( fNextSyncType.name() ) );
01282 tipText.append( CSL1("</qt>") );
01283
01284 QToolTip::remove(fTray);
01285 QToolTip::add(fTray,tipText);
01286 emitDCOPSignal( "kpilotDaemonStatusChanged()", QByteArray() );
01287
01288 QByteArray data;
01289 QDataStream arg(data, IO_WriteOnly);
01290 arg << lastSyncDate();
01291 arg << shortStatusString();
01292 arg << configuredConduitList();
01293 arg << logFileName();
01294 arg << userName();
01295 arg << pilotDevice();
01296 arg << killDaemonOnExit();
01297 emitDCOPSignal( "kpilotDaemonStatusDetails(QDateTime,QString,QStringList,QString,QString,QString,bool)", data );
01298 }
01299
01300 static KCmdLineOptions daemonoptions[] = {
01301 #ifdef DEBUG
01302 {"debug <level>", I18N_NOOP("Set debugging level"), "0"},
01303 #endif
01304 { "device <device>", I18N_NOOP("Device to try first"), ""},
01305 {"fail-silently", ("Exit instead of complaining "
01306 "about bad configuration files"), 0},
01307 KCmdLineLastOption
01308 } ;
01309
01310
01311 int main(int argc, char **argv)
01312 {
01313 FUNCTIONSETUP;
01314
01315 KLocale::setMainCatalogue("kpilot");
01316
01317 KAboutData about("kpilotDaemon",
01318 I18N_NOOP("KPilot Daemon"),
01319 KPILOT_VERSION,
01320 "KPilot - HotSync software for KDE\n\n",
01321 KAboutData::License_GPL,
01322 "(c) 1998-2000,2001, Dan Pilone (c) 2000-2004, Adriaan de Groot",
01323 0L,
01324 "http://www.kpilot.org/"
01325 );
01326 about.addAuthor("Dan Pilone",
01327 I18N_NOOP("Project Leader"),
01328 "pilone@slac.com");
01329 about.addAuthor("Adriaan de Groot",
01330 I18N_NOOP("Maintainer"),
01331 "groot@kde.org", "http://www.kpilot.org/");
01332 about.addAuthor("Reinhold Kainhofer",
01333 I18N_NOOP("Developer"),
01334 "reinhold@kainhofer.com", "http://reinhold.kainhofer.com/Linux/");
01335 aboutData = &about;
01336
01337
01338 KCmdLineArgs::init(argc, argv, &about);
01339 KCmdLineArgs::addCmdLineOptions(daemonoptions,"kpilotconfig");
01340 KUniqueApplication::addCmdLineOptions();
01341 KCmdLineArgs *p = KCmdLineArgs::parsedArgs();
01342
01343 #ifdef DEBUG
01344 KPilotConfig::getDebugLevel(p);
01345 #endif
01346 if (!KUniqueApplication::start())
01347 {
01348 if (p->isSet("device")){
01349
01350
01351 DCOPClient d;
01352 QString dev(p->getOption("device"));
01353 QByteArray data;
01354 QDataStream arg(data, IO_WriteOnly);
01355 arg << dev;
01356 if (d.attach()){
01357 d.send("kpilotDaemon", "KPilotDaemonIface", "setTempDevice(QString)", data );
01358 d.detach();
01359 }
01360 }
01361 return 0;
01362 }
01363 KUniqueApplication a(true, true);
01364
01365
01366
01367
01368 {
01369
01370
01371 if (KPilotSettings::configVersion() < KPilotConfig::ConfigurationVersion)
01372 {
01373 kdError() << k_funcinfo
01374 << ": Is still not configured for use."
01375 << endl;
01376 if (!p->isSet("fail-silently"))
01377 {
01378 KPilotConfig::sorryVersionOutdated(KPilotSettings::configVersion());
01379 }
01380 return 1;
01381 }
01382
01383 #ifdef DEBUG
01384 DEBUGKPILOT << fname
01385 << ": Configuration version "
01386 << KPilotSettings::configVersion() << endl;
01387 #endif
01388 }
01389
01390
01391 PilotDaemon *gPilotDaemon = new PilotDaemon();
01392
01393 if (p->isSet("device"))
01394 gPilotDaemon->setTempDevice(p->getOption("device"));
01395
01396 if (gPilotDaemon->status() == PilotDaemon::ERROR)
01397 {
01398 delete gPilotDaemon;
01399
01400 gPilotDaemon = 0;
01401 kdError() << k_funcinfo
01402 << ": **\n"
01403 ": Failed to start up daemon\n"
01404 ": due to errors constructing it.\n" ": **" << endl;
01405 return 2;
01406 }
01407
01408 gPilotDaemon->showTray();
01409
01410 return a.exec();
01411 }
01412
01413
01414