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