kpilot/kpilot

kpilot.cc

00001 /* KPilot
00002 **
00003 ** Copyright (C) 1998-2001 by Dan Pilone
00004 ** Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005 **
00006 ** This is the main program in KPilot.
00007 **
00008 */
00009 
00010 /*
00011 ** This program is free software; you can redistribute it and/or modify
00012 ** it under the terms of the GNU General Public License as published by
00013 ** the Free Software Foundation; either version 2 of the License, or
00014 ** (at your option) any later version.
00015 **
00016 ** This program is distributed in the hope that it will be useful,
00017 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00018 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00019 ** GNU General Public License for more details.
00020 **
00021 ** You should have received a copy of the GNU General Public License
00022 ** along with this program in a file called COPYING; if not, write to
00023 ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00024 ** MA 02110-1301, USA.
00025 */
00026 
00027 /*
00028 ** Bug reports and questions can be sent to kde-pim@kde.org
00029 */
00030 
00031 
00032 #include "options.h"
00033 
00034 #include <qfile.h>
00035 #include <qptrlist.h>
00036 #include <qstring.h>
00037 #include <qvbox.h>
00038 #include <qtimer.h>
00039 
00040 #include <kjanuswidget.h>
00041 #include <kurl.h>
00042 #include <kmessagebox.h>
00043 #include <kstatusbar.h>
00044 #include <kconfig.h>
00045 #include <kwin.h>
00046 #include <kcombobox.h>
00047 #include <kmenubar.h>
00048 #include <kstandarddirs.h>
00049 #include <kaboutdata.h>
00050 #include <kcmdlineargs.h>
00051 #include <kiconloader.h>
00052 #include <kdebug.h>
00053 #include <kaction.h>
00054 #include <kactionclasses.h>
00055 #include <kstdaction.h>
00056 #include <kuniqueapplication.h>
00057 #include <kkeydialog.h>
00058 #include <kedittoolbar.h>
00059 #include <kcmultidialog.h>
00060 #include <kprogress.h>
00061 #include <klibloader.h>
00062 
00063 
00064 #include "kpilotConfigDialog.h"
00065 #include "kpilotConfig.h"
00066 #include "kpilotConfigWizard.h"
00067 
00068 #include "pilotComponent.h"
00069 #include "pilotDatabase.h"
00070 
00071 #include "addressWidget.h"
00072 #include "memoWidget.h"
00073 #include "fileInstallWidget.h"
00074 #include "logWidget.h"
00075 #include "dbviewerWidget.h"
00076 #include "datebookWidget.h"
00077 #include "todoWidget.h"
00078 
00079 #include "conduitConfigDialog.h"
00080 
00081 #ifndef _KPILOT_PILOTDAEMON_H
00082 #include "pilotDaemonDCOP.h"
00083 #endif
00084 
00085 #ifndef __PILOTDAEMONDCOP_STUB__
00086 #include "pilotDaemonDCOP_stub.h"
00087 #endif
00088 
00089 #include "kpilot.moc"
00090 
00091 class KPilotInstaller::KPilotPrivate
00092 {
00093 public:
00094     typedef QPtrList<PilotComponent> ComponentList;
00095 
00096 private:
00097     ComponentList  fPilotComponentList;
00098 
00099 public:
00100     ComponentList &list() { return fPilotComponentList; } ;
00101 } ;
00102 
00103 KPilotInstaller::KPilotInstaller() :
00104     DCOPObject("KPilotIface"),
00105     KMainWindow(0),
00106     fDaemonStub(new PilotDaemonDCOP_stub("kpilotDaemon",
00107         "KPilotDaemonIface")),
00108     fP(new KPilotPrivate),
00109     fQuitAfterCopyComplete(false),
00110     fManagingWidget(0L),
00111     fDaemonWasRunning(true),
00112     fAppStatus(Startup),
00113     fFileInstallWidget(0L),
00114     fLogWidget(0L)
00115 {
00116     FUNCTIONSETUP;
00117 
00118     readConfig();
00119     setupWidget();
00120 
00121 #ifdef DEBUG
00122     PilotRecord::allocationInfo();
00123 #endif
00124     fConfigureKPilotDialogInUse = false;
00125 
00126 }
00127 
00128 KPilotInstaller::~KPilotInstaller()
00129 {
00130     FUNCTIONSETUP;
00131     killDaemonIfNeeded();
00132     delete fDaemonStub;
00133 #ifdef DEBUG
00134     PilotRecord::allocationInfo();
00135     (void) PilotDatabase::instanceCount();
00136 #endif
00137 }
00138 
00139 void KPilotInstaller::killDaemonIfNeeded()
00140 {
00141     FUNCTIONSETUP;
00142     if (KPilotSettings::killDaemonAtExit())
00143     {
00144         if (!fDaemonWasRunning)
00145         {
00146 #ifdef DEBUG
00147             DEBUGKPILOT << fname << ": Killing daemon." << endl;
00148 #endif
00149 
00150             getDaemon().quitNow();
00151         }
00152     }
00153 }
00154 
00155 void KPilotInstaller::startDaemonIfNeeded()
00156 {
00157     FUNCTIONSETUP;
00158 
00159     fAppStatus=WaitingForDaemon;
00160 
00161     QString daemonError;
00162     QCString daemonDCOP;
00163     int daemonPID;
00164 
00165     QString s = getDaemon().statusString();
00166 
00167 #ifdef DEBUG
00168     DEBUGKPILOT << fname << ": Daemon status is "
00169         << ( s.isEmpty() ? CSL1("<none>") : s ) << endl;
00170 #endif
00171 
00172     if ((s.isEmpty()) || (!getDaemon().ok()))
00173     {
00174 #ifdef DEBUG
00175         DEBUGKPILOT << fname
00176             << ": Daemon not responding, trying to start it."
00177             << endl;
00178 #endif
00179         fLogWidget->addMessage(i18n("Starting the KPilot daemon ..."));
00180         fDaemonWasRunning = false;
00181     }
00182     else
00183     {
00184         fDaemonWasRunning = true;
00185     }
00186 
00187     if (!fDaemonWasRunning && KApplication::startServiceByDesktopName(
00188         CSL1("kpilotdaemon"),
00189         QString::null, &daemonError, &daemonDCOP, &daemonPID
00190             , "0" /* no notify */
00191         ))
00192     {
00193         kdError() << k_funcinfo
00194             << ": Can't start daemon : " << daemonError << endl;
00195         if (fLogWidget)
00196         {
00197             fLogWidget->addMessage(i18n("Could not start the "
00198                 "KPilot daemon. The system error message "
00199                 "was: &quot;%1&quot;").arg(daemonError));
00200         }
00201         fAppStatus=Error;
00202     }
00203     else
00204     {
00205 #ifdef DEBUG
00206         s = getDaemon().statusString();
00207         DEBUGKPILOT << fname << ": Daemon status is " << s << endl;
00208 #endif
00209         if (fLogWidget)
00210         {
00211             int wordoffset;
00212             s.remove(0,12);
00213             wordoffset=s.find(';');
00214             if (wordoffset>0) s.truncate(wordoffset);
00215 
00216             fLogWidget->addMessage(
00217                 i18n("Daemon status is `%1'")
00218                 .arg(s.isEmpty() ? i18n("not running") : s ));
00219         }
00220         fAppStatus=Normal;
00221     }
00222 }
00223 
00224 void KPilotInstaller::readConfig()
00225 {
00226     FUNCTIONSETUP;
00227 
00228     KPilotSettings::self()->readConfig();
00229 
00230     (void) Pilot::setupPilotCodec(KPilotSettings::encoding());
00231     (void) Pilot::setupPilotCodec(KPilotSettings::encoding());
00232 
00233     if (fLogWidget)
00234     {
00235         fLogWidget->addMessage(i18n("Using character set %1 on "
00236             "the handheld.")
00237             .arg(Pilot::codecName()));
00238     }
00239 }
00240 
00241 
00242 void KPilotInstaller::setupWidget()
00243 {
00244     FUNCTIONSETUP;
00245 
00246 #ifdef DEBUG
00247     DEBUGKPILOT << fname << ": Creating central widget." << endl;
00248 #endif
00249 
00250     setCaption(CSL1("KPilot"));
00251     setMinimumSize(500, 405);
00252 
00253 
00254     fManagingWidget = new KJanusWidget(this,"mainWidget",
00255         KJanusWidget::IconList);
00256     fManagingWidget->setMinimumSize(fManagingWidget->sizeHint());
00257     fManagingWidget->show();
00258     setCentralWidget(fManagingWidget);
00259     connect( fManagingWidget, SIGNAL( aboutToShowPage ( QWidget* ) ),
00260             this, SLOT( slotAboutToShowComponent( QWidget* ) ) );
00261 
00262     initIcons();
00263     initMenu();
00264     initComponents();
00265 
00266     setMinimumSize(sizeHint() + QSize(10,60));
00267 
00268     createGUI(CSL1("kpilotui.rc"), false);
00269 #ifdef DEBUG
00270     DEBUGKPILOT << fname
00271         << ": Got XML from "
00272         << xmlFile() << " and " << localXMLFile() << endl;
00273 #endif
00274     setAutoSaveSettings();
00275 }
00276 
00277 void KPilotInstaller::initComponents()
00278 {
00279     FUNCTIONSETUP;
00280 
00281     QString defaultDBPath = KPilotConfig::getDefaultDBPath();
00282 
00283 #ifdef DEBUG
00284     DEBUGKPILOT << fname << ": Creating component pages." << endl;
00285 #endif
00286 
00287     QPixmap pixmap;
00288     QString pixfile;
00289     QWidget *w;
00290 
00291 #define ADDICONPAGE(a,b) \
00292     pixmap = KGlobal::iconLoader()->loadIcon(b, KIcon::Desktop, 64); \
00293     w = getManagingWidget()->addVBoxPage(a,QString::null, pixmap) ;
00294 
00295     ADDICONPAGE(i18n("HotSync"),CSL1("kpilotbhotsync"));
00296     fLogWidget = new LogWidget(w);
00297     addComponentPage(fLogWidget, i18n("HotSync"));
00298     fLogWidget->setShowTime(true);
00299 
00300     ADDICONPAGE(i18n("To-do Viewer"),CSL1("kpilottodo"));
00301     addComponentPage(new TodoWidget(w,defaultDBPath),
00302         i18n("To-do Viewer"));
00303 
00304     ADDICONPAGE(i18n("Address Viewer"),CSL1("kpilotaddress"));
00305     addComponentPage(new AddressWidget(w,defaultDBPath),
00306         i18n("Address Viewer"));
00307 
00308     ADDICONPAGE(i18n("Memo Viewer"),CSL1("kpilotknotes"));
00309     addComponentPage(new MemoWidget(w, defaultDBPath),
00310         i18n("Memo Viewer"));
00311 
00312     ADDICONPAGE(i18n("File Installer"),CSL1("kpilotfileinstaller"));
00313     fFileInstallWidget = new FileInstallWidget(
00314         w,defaultDBPath);
00315     addComponentPage(fFileInstallWidget, i18n("File Installer"));
00316 
00317     ADDICONPAGE(i18n("Generic DB Viewer"),CSL1("kpilotdb"));
00318     addComponentPage(new GenericDBWidget(w,defaultDBPath),
00319         i18n("Generic DB Viewer"));
00320 
00321 #undef ADDICONPAGE
00322 
00323     QTimer::singleShot(500,this,SLOT(initializeComponents()));
00324 }
00325 
00326 
00327 
00328 void KPilotInstaller::initIcons()
00329 {
00330     FUNCTIONSETUP;
00331 
00332 }
00333 
00334 
00335 
00336 void KPilotInstaller::slotAboutToShowComponent( QWidget *c )
00337 {
00338     FUNCTIONSETUP;
00339     int ix = fManagingWidget->pageIndex( c );
00340     PilotComponent*compToShow = fP->list().at(ix);
00341 #ifdef DEBUG
00342     DEBUGKPILOT << fname
00343         << ": Index: " << ix
00344         << ", Widget=" << c
00345         << ", ComToShow=" << compToShow << endl;
00346 #endif
00347     for ( PilotComponent *comp = fP->list().first(); comp; comp = fP->list().next() )
00348     {
00349         // Load/Unload the data needed
00350         comp->showKPilotComponent( comp == compToShow );
00351     }
00352 }
00353 
00354 void KPilotInstaller::slotSelectComponent(PilotComponent * c)
00355 {
00356     FUNCTIONSETUP;
00357     if (!c)
00358     {
00359         kdWarning() << k_funcinfo << ": Not a widget." << endl;
00360         return;
00361     }
00362 
00363     QObject *o = c->parent();
00364     if (!o)
00365     {
00366         kdWarning() << k_funcinfo << ": No parent." << endl;
00367         return;
00368     }
00369 
00370     QWidget *parent = dynamic_cast<QWidget *>(o);
00371     if (!parent)
00372     {
00373         kdWarning() << k_funcinfo << ": No widget parent." << endl;
00374         return;
00375     }
00376 
00377     int index = fManagingWidget->pageIndex(parent);
00378 
00379     if (index < 0)
00380     {
00381         kdWarning() << k_funcinfo << ": Index " << index << endl;
00382         return;
00383     }
00384 
00385     for ( PilotComponent *comp = fP->list().first(); comp; comp = fP->list().next() )
00386     {
00387         // Load/Unload the data needed
00388         comp->showKPilotComponent( comp == c );
00389     }
00390     fManagingWidget->showPage(index);
00391 }
00392 
00393 
00394 
00395 
00396 void KPilotInstaller::slotBackupRequested()
00397 {
00398     FUNCTIONSETUP;
00399     setupSync(SyncAction::SyncMode::eBackup,
00400         i18n("Next sync will be a backup. ") +
00401         i18n("Please press the HotSync button."));
00402 }
00403 
00404 void KPilotInstaller::slotRestoreRequested()
00405 {
00406     FUNCTIONSETUP;
00407     setupSync(SyncAction::SyncMode::eRestore,
00408         i18n("Next sync will restore the Pilot from backup. ") +
00409         i18n("Please press the HotSync button."));
00410 }
00411 
00412 void KPilotInstaller::slotHotSyncRequested()
00413 {
00414     FUNCTIONSETUP;
00415     setupSync(SyncAction::SyncMode::eHotSync,
00416         i18n("Next sync will be a regular HotSync. ") +
00417         i18n("Please press the HotSync button."));
00418 }
00419 
00420 void KPilotInstaller::slotFullSyncRequested()
00421 {
00422     FUNCTIONSETUP;
00423     setupSync(SyncAction::SyncMode::eFullSync,
00424         i18n("Next sync will be a Full Sync. ") +
00425         i18n("Please press the HotSync button."));
00426 }
00427 
00428 void KPilotInstaller::slotHHtoPCRequested()
00429 {
00430     FUNCTIONSETUP;
00431     setupSync(SyncAction::SyncMode::eCopyHHToPC,
00432         i18n("Next sync will copy Handheld data to PC. ") +
00433         i18n("Please press the HotSync button."));
00434 }
00435 
00436 void KPilotInstaller::slotPCtoHHRequested()
00437 {
00438     FUNCTIONSETUP;
00439     setupSync(SyncAction::SyncMode::eCopyPCToHH,
00440         i18n("Next sync will copy PC data to Handheld. ") +
00441         i18n("Please press the HotSync button."));
00442 }
00443 
00444 /* virtual DCOP */ ASYNC KPilotInstaller::daemonStatus(int i)
00445 {
00446     FUNCTIONSETUP;
00447 #ifdef DEBUG
00448     DEBUGKPILOT << fname << ": Received daemon message " << i << endl;
00449 #endif
00450 
00451     switch(i)
00452     {
00453     case KPilotDCOP::StartOfHotSync :
00454         if (fAppStatus==Normal)
00455         {
00456             fAppStatus=WaitingForDaemon;
00457             componentPreSync();
00458         }
00459         break;
00460     case KPilotDCOP::EndOfHotSync :
00461         if (fAppStatus==WaitingForDaemon)
00462         {
00463             componentPostSync();
00464             fAppStatus=Normal;
00465         }
00466         break;
00467     case KPilotDCOP::DaemonQuit :
00468         if (fLogWidget)
00469         {
00470             fLogWidget->logMessage(i18n("The daemon has exited."));
00471             fLogWidget->logMessage(i18n("No further HotSyncs are possible."));
00472             fLogWidget->logMessage(i18n("Restart the daemon to HotSync again."));
00473         }
00474         fAppStatus=WaitingForDaemon;
00475         break;
00476     case KPilotDCOP::None :
00477         kdWarning() << k_funcinfo << ": Unhandled status message " << i << endl;
00478         break;
00479     }
00480 }
00481 
00482 /* virtual DCOP*/ int KPilotInstaller::kpilotStatus()
00483 {
00484     return status();
00485 }
00486 
00487 bool KPilotInstaller::componentPreSync()
00488 {
00489     FUNCTIONSETUP;
00490 
00491     QString reason;
00492     QString rprefix(i18n("Cannot start a Sync now. %1"));
00493 
00494     for (fP->list().first();
00495         fP->list().current(); fP->list().next())
00496     {
00497 #ifdef DEBUG
00498         DEBUGKPILOT << fname
00499             << ": Pre-sync for builtin "
00500             << fP->list().current()->name() << endl;
00501 #endif
00502         if (!fP->list().current()->preHotSync(reason))
00503             break;
00504     }
00505 
00506     if (!reason.isNull())
00507     {
00508         KMessageBox::sorry(this,
00509             rprefix.arg(reason),
00510             i18n("Cannot start Sync"));
00511         return false;
00512     }
00513     return true;
00514 }
00515 
00516 void KPilotInstaller::componentPostSync()
00517 {
00518     FUNCTIONSETUP;
00519 
00520     for (fP->list().first();
00521         fP->list().current(); fP->list().next())
00522     {
00523 #ifdef DEBUG
00524         DEBUGKPILOT << fname
00525             << ": Post-sync for builtin "
00526             << fP->list().current()->name() << endl;
00527 #endif
00528         fP->list().current()->postHotSync();
00529     }
00530 }
00531 
00532 void KPilotInstaller::setupSync(int kind, const QString & message)
00533 {
00534     FUNCTIONSETUP;
00535 
00536     if (!componentPreSync())
00537     {
00538         return;
00539     }
00540     if (!message.isEmpty())
00541     {
00542         QString m(message);
00543         if (fLogWidget)
00544         {
00545             fLogWidget->logMessage(m);
00546         }
00547     }
00548     getDaemon().requestSync(kind);
00549 }
00550 
00551 void KPilotInstaller::closeEvent(QCloseEvent * e)
00552 {
00553     FUNCTIONSETUP;
00554 
00555     quit();
00556     e->accept();
00557 }
00558 
00559 void KPilotInstaller::initMenu()
00560 {
00561     FUNCTIONSETUP;
00562 
00563     KAction *a;
00564 
00565     KActionMenu *syncPopup;
00566 
00567     syncPopup = new KActionMenu(i18n("HotSync"), CSL1("kpilot"),
00568         actionCollection(), "popup_hotsync");
00569     syncPopup->setToolTip(i18n("Select the kind of HotSync to perform next."));
00570     syncPopup->setWhatsThis(i18n("Select the kind of HotSync to perform next. "
00571         "This applies only to the next HotSync; to change the default, use "
00572         "the configuration dialog."));
00573     connect(syncPopup, SIGNAL(activated()),
00574         this, SLOT(slotHotSyncRequested()));
00575 
00576     // File actions, keep this list synced with kpilotui.rc and pilotDaemon.cc
00577     a = new KAction(i18n("&HotSync"), CSL1("hotsync"), 0,
00578         this, SLOT(slotHotSyncRequested()),
00579         actionCollection(), "file_hotsync");
00580     a->setToolTip(i18n("Next HotSync will be normal HotSync."));
00581     a->setWhatsThis(i18n("Tell the daemon that the next HotSync "
00582         "should be a normal HotSync."));
00583     syncPopup->insert(a);
00584 
00585     a = new KAction(i18n("Full&Sync"), CSL1("fullsync"), 0,
00586         this, SLOT(slotFullSyncRequested()),
00587         actionCollection(), "file_fullsync");
00588     a->setToolTip(i18n("Next HotSync will be a FullSync."));
00589     a->setWhatsThis(i18n("Tell the daemon that the next HotSync "
00590         "should be a FullSync (check data on both sides)."));
00591     syncPopup->insert(a);
00592 
00593     a = new KAction(i18n("&Backup"), CSL1("backup"), 0,
00594         this, SLOT(slotBackupRequested()),
00595         actionCollection(), "file_backup");
00596     a->setToolTip(i18n("Next HotSync will be backup."));
00597     a->setWhatsThis(i18n("Tell the daemon that the next HotSync "
00598         "should back up the Handheld to the PC."));
00599     syncPopup->insert(a);
00600 
00601     a = new KAction(i18n("&Restore"), CSL1("restore"), 0,
00602         this, SLOT(slotRestoreRequested()),
00603         actionCollection(), "file_restore");
00604     a->setToolTip(i18n("Next HotSync will be restore."));
00605     a->setWhatsThis(i18n("Tell the daemon that the next HotSync "
00606         "should restore the Handheld from data on the PC."));
00607     syncPopup->insert(a);
00608 
00609     a = new KAction(i18n("Copy Handheld to PC"), QString::null, 0,
00610         this, SLOT(slotHHtoPCRequested()),
00611         actionCollection(), "file_HHtoPC");
00612     a->setToolTip(i18n("Next HotSync will be backup."));
00613     a->setWhatsThis(i18n("Tell the daemon that the next HotSync "
00614         "should copy all data from the Handheld to the PC, "
00615         "overwriting entries on the PC."));
00616     syncPopup->insert(a);
00617 
00618     a = new KAction(i18n("Copy PC to Handheld"), QString::null, 0,
00619         this, SLOT(slotPCtoHHRequested()),
00620         actionCollection(), "file_PCtoHH");
00621     a->setToolTip(i18n("Next HotSync will copy PC to Handheld."));
00622     a->setWhatsThis(i18n("Tell the daemon that the next HotSync "
00623         "should copy all data from the PC to the Handheld, "
00624         "overwriting entries on the Handheld."));
00625     syncPopup->insert(a);
00626 
00627 
00628 #if 0
00629     a = new KAction(i18n("&List Only"),CSL1("listsync"),0,
00630         this,SLOT(slotTestSyncRequested()),
00631         actionCollection(), "file_list");
00632     a->setToolTip(i18n("Next HotSync will list databases."));
00633     a->setWhatsThis(i18n("Tell the daemon that the next HotSync "
00634         "should just list the files on the Handheld and do nothing "
00635         "else."));
00636     syncPopup->insert(a);
00637 #endif
00638 
00639 
00640     a = new KAction(i18n("Rese&t Link"),CSL1("reload"), 0,
00641         this, SLOT(slotResetLink()),
00642         actionCollection(),"file_reload");
00643     a->setToolTip(i18n("Reset the device connection."));
00644     a->setWhatsThis(i18n("Try to reset the daemon and its connection "
00645         "to the Handheld."));
00646 
00647 
00648     a = KStdAction::quit(this, SLOT(quit()), actionCollection());
00649     a->setWhatsThis(i18n("Quit KPilot, (and stop the daemon "
00650         "if configured that way)."));
00651 
00652     // View actions
00653 
00654     // Options actions
00655     createStandardStatusBarAction();
00656     setStandardToolBarMenuEnabled(true);
00657 
00658     (void) KStdAction::keyBindings(this, SLOT(optionsConfigureKeys()),
00659         actionCollection());
00660     (void) KStdAction::configureToolbars(this, SLOT(optionsConfigureToolbars()),
00661         actionCollection());
00662     (void) KStdAction::preferences(this, SLOT(configure()),
00663         actionCollection());
00664 
00665     a = new KAction(i18n("Configuration &Wizard..."), CSL1("wizard"), 0,
00666         this, SLOT(configureWizard()),
00667         actionCollection(), "options_configure_wizard");
00668     a->setWhatsThis(i18n("Configure KPilot using the configuration wizard."));
00669 
00670 }
00671 
00672 void KPilotInstaller::fileInstalled(int)
00673 {
00674     FUNCTIONSETUP;
00675 }
00676 
00677 void KPilotInstaller::quit()
00678 {
00679     FUNCTIONSETUP;
00680 
00681     for (fP->list().first();
00682         fP->list().current(); fP->list().next())
00683     {
00684         QString reason;
00685         if (!fP->list().current()->preHotSync(reason))
00686         {
00687             kdWarning() << k_funcinfo
00688                 << ": Couldn't save "
00689                 << fP->list().current()->name()
00690                 << endl;
00691         }
00692     }
00693 
00694     killDaemonIfNeeded();
00695     kapp->quit();
00696 }
00697 
00698 void KPilotInstaller::addComponentPage(PilotComponent * p,
00699     const QString & name)
00700 {
00701     FUNCTIONSETUP;
00702 
00703     if (!p)
00704     {
00705         kdWarning() << k_funcinfo
00706             << ": Adding NULL component?" << endl;
00707         return;
00708     }
00709 
00710 #ifdef DEBUG
00711     DEBUGKPILOT << fname
00712         << ": Adding component @"
00713         << (unsigned long) p << " called " << p->name("(none)") << endl;
00714 #endif
00715 
00716     fP->list().append(p);
00717 
00718     // The first component added gets id 1, while the title
00719     // screen -- added elsewhere -- has id 0.
00720     //
00721     // fManagingWidget->addWidget(p, fP->list().count());
00722 
00723 
00724     const char *componentname = p->name("(none)");
00725     char *actionname = 0L;
00726     int actionnameLength = 0;
00727 
00728     if (strncmp(componentname, "component_", 10) == 0)
00729     {
00730         actionnameLength = strlen(componentname) - 10 + 8;
00731         actionname = new char[actionnameLength];
00732 
00733         strlcpy(actionname, "view_", actionnameLength);
00734         strlcat(actionname, componentname + 10, actionnameLength);
00735     }
00736     else
00737     {
00738         actionnameLength = strlen(componentname) + 8;
00739         actionname = new char[actionnameLength];
00740 
00741         strlcpy(actionname, "view_", actionnameLength);
00742         strlcat(actionname, componentname, actionnameLength);
00743     }
00744 
00745 #ifdef DEBUG
00746     DEBUGKPILOT << fname
00747         << ": Using component action name "
00748         << name << " for " << actionname << endl;
00749 #endif
00750 
00751     KToggleAction *pt =
00752         new KToggleAction(name, /* "kpilot" -- component icon, */ 0,
00753         p, SLOT(slotShowComponent()),
00754         actionCollection(), actionname);
00755 
00756     pt->setExclusiveGroup(CSL1("view_menu"));
00757 
00758     connect(p, SIGNAL(showComponent(PilotComponent *)),
00759         this, SLOT(slotSelectComponent(PilotComponent *)));
00760 }
00761 
00762 /* slot */ void KPilotInstaller::initializeComponents()
00763 {
00764     FUNCTIONSETUP;
00765 
00766 /*  for (PilotComponent *p = fP->list().first();
00767         p ; p = fP->list().next())
00768     {
00769         p->initialize();
00770     }*/
00771 }
00772 
00773 
00774 void KPilotInstaller::optionsConfigureKeys()
00775 {
00776     FUNCTIONSETUP;
00777     KKeyDialog::configure( actionCollection() );
00778 }
00779 
00780 void KPilotInstaller::optionsConfigureToolbars()
00781 {
00782     FUNCTIONSETUP;
00783     // use the standard toolbar editor
00784     // This was added in KDE 3.1
00785     saveMainWindowSettings( KGlobal::config(), autoSaveGroup() );
00786     KEditToolbar dlg(actionCollection());
00787     connect(&dlg, SIGNAL(newToolbarConfig()), this, SLOT(slotNewToolbarConfig()));
00788     dlg.exec();
00789 }
00790 
00791 
00792 void KPilotInstaller::slotNewToolbarConfig()
00793 {
00794     FUNCTIONSETUP;
00795     // recreate our GUI
00796     createGUI();
00797     applyMainWindowSettings( KGlobal::config(), autoSaveGroup() );
00798 }
00799 
00800 void KPilotInstaller::slotResetLink()
00801 {
00802     FUNCTIONSETUP;
00803     getDaemon().reloadSettings();
00804 }
00805 
00806 /*
00807 ** Can't be a member function because it needs to be called even with no KPilotInstaller.
00808 */
00809 static bool runConfigure(PilotDaemonDCOP_stub &daemon,QWidget *parent)
00810 {
00811     FUNCTIONSETUP;
00812     bool ret = false;
00813 
00814     // Display the (modal) options page.
00815     //
00816     //
00817     int rememberedSync = daemon.nextSyncType();
00818     daemon.requestSync(0);
00819 
00820     KPilotSettings::self()->readConfig();
00821 
00822     KCMultiDialog *options = new KCMultiDialog( KDialogBase::Plain, i18n("Configuration"), parent, "KPilotPreferences", true );
00823     options->addModule( CSL1("kpilot_config.desktop") );
00824 
00825     if (!options)
00826     {
00827         kdError() << k_funcinfo
00828             << ": Can't allocate KPilotOptions object" << endl;
00829         daemon.requestSync(rememberedSync);
00830         return false;
00831     }
00832 
00833     int r = options->exec();
00834 
00835     if ( r && options->result() )
00836     {
00837 #ifdef DEBUG
00838         DEBUGKPILOT << fname << ": Updating link." << endl;
00839 #endif
00840 
00841         // The settings are changed in the external module!!!
00842         KPilotSettings::self()->config()->sync();
00843         KPilotSettings::self()->readConfig();
00844 
00845         // Update the daemon to reflect new settings.
00846         // @TODO: This should also be done when pressing apply without
00847         // closing the dialog.
00848         //
00849         daemon.reloadSettings();
00850         ret = true;
00851     }
00852 
00853     KPILOT_DELETE(options);
00854     daemon.requestSync(rememberedSync);
00855 
00856 #ifdef DEBUG
00857     DEBUGKPILOT << fname << ": Done with options." << endl;
00858 #endif
00859 
00860     KPilotConfig::sync();
00861     return ret;
00862 }
00863 
00864 /*
00865  * Run the config wizard -- this takes a little library magic, and
00866  * it might fail entirely; returns false if no wizard could be run,
00867  * or true if the wizard runs (says nothing about it being OK'ed or
00868  * canceled, though).
00869  */
00870 typedef enum { Failed, OK, Cancel } WizardResult;
00871 static WizardResult runWizard(PilotDaemonDCOP_stub &daemon,QWidget *parent)
00872 {
00873     FUNCTIONSETUP;
00874     WizardResult ret = Failed ;
00875     int rememberedSync = daemon.nextSyncType();
00876     daemon.requestSync(0);
00877 
00878     KPilotSettings::self()->readConfig();
00879     // Declarations at top because of goto's in this function
00880     ConfigWizard *(* f) (QWidget *, int) = 0L ;
00881     ConfigWizard *w = 0L;
00882     KLibrary *l = KLibLoader::self()->library("kcm_kpilot");
00883 
00884     if (!l)
00885     {
00886         kdWarning() << k_funcinfo << ": Couldn't load library!" << endl;
00887         goto sorry;
00888     }
00889 
00890     if (l->hasSymbol("create_wizard"))
00891     {
00892         f = ( ConfigWizard * (*) (QWidget *, int) ) (l->symbol("create_wizard")) ;
00893     }
00894 
00895     if (!f)
00896     {
00897         kdWarning() << k_funcinfo << ": No create_wizard() in library." << endl;
00898         goto sorry;
00899     }
00900 
00901     w = f(parent,ConfigWizard::Standalone);
00902     if (!w)
00903     {
00904         kdWarning() << k_funcinfo << ": Can't create wizard." << endl;
00905         goto sorry;
00906     }
00907 
00908     if (w->exec())
00909     {
00910         KPilotSettings::self()->readConfig();
00911         ret = OK;
00912     }
00913     else
00914     {
00915         ret = Cancel;
00916     }
00917     KPILOT_DELETE(w);
00918 
00919 sorry:
00920     if (Failed == ret)
00921     {
00922         KMessageBox::sorry(parent,
00923             i18n("The library containing the configuration wizard for KPilot "
00924                 "could not be loaded, and the wizard is not available. "
00925                 "Please try to use the regular configuration dialog."),
00926                 i18n("Wizard Not Available"));
00927     }
00928 
00929     if (OK == ret)
00930     {
00931         KPilotConfig::updateConfigVersion();
00932         KPilotSettings::writeConfig();
00933         KPilotConfig::sync();
00934     }
00935 
00936     daemon.requestSync(rememberedSync);
00937     return ret;
00938 }
00939 
00940 void KPilotInstaller::componentUpdate()
00941 {
00942     FUNCTIONSETUP;
00943 
00944     QString defaultDBPath = KPilotConfig::getDefaultDBPath();
00945     bool dbPathChanged = false;
00946 
00947     for (fP->list().first();
00948         fP->list().current();
00949         fP->list().next())
00950     {
00951 // TODO_RK: update the current component to use the new settings
00952 //          fP->list().current()->initialize();
00953         PilotComponent *p = fP->list().current();
00954         if (p && (p->dbPath() != defaultDBPath))
00955         {
00956             dbPathChanged = true;
00957             p->setDBPath(defaultDBPath);
00958         }
00959     }
00960 
00961     if (!dbPathChanged) // done if the username didn't change
00962     {
00963         return;
00964     }
00965 
00966     // Otherwise, need to re-load the databases
00967     //
00968     if (fLogWidget)
00969     {
00970         fLogWidget->logMessage(i18n("Changed username to `%1'.")
00971             .arg(KPilotSettings::userName()));
00972         fManagingWidget->showPage(0);
00973         slotAboutToShowComponent(fLogWidget);
00974     }
00975     else
00976     {
00977         int ix = fManagingWidget->activePageIndex();
00978         PilotComponent *component = 0L;
00979         if (ix>=0)
00980         {
00981             component = fP->list().at(ix);
00982         }
00983         if (component)
00984         {
00985             component->hideComponent(); // Throw away current data
00986             component->showComponent(); // Reload
00987         }
00988     }
00989 }
00990 
00991 /* virtual DCOP */ ASYNC KPilotInstaller::configureWizard()
00992 {
00993     FUNCTIONSETUP;
00994 
00995     if ( fAppStatus!=Normal || fConfigureKPilotDialogInUse )
00996     {
00997         if (fLogWidget)
00998         {
00999             fLogWidget->addMessage(i18n("Cannot run KPilot's configuration wizard right now (KPilot's UI is already busy)."));
01000         }
01001         return;
01002     }
01003     fAppStatus=UIBusy;
01004     fConfigureKPilotDialogInUse = true;
01005 
01006     if (runWizard(getDaemon(),this) == OK)
01007     {
01008         componentUpdate();
01009     }
01010 
01011     fConfigureKPilotDialogInUse = false;
01012     fAppStatus=Normal;
01013 }
01014 
01015 /* virtual DCOP */ ASYNC KPilotInstaller::configure()
01016 {
01017     FUNCTIONSETUP;
01018 
01019     if ( fAppStatus!=Normal || fConfigureKPilotDialogInUse )
01020     {
01021         if (fLogWidget)
01022         {
01023             fLogWidget->addMessage(i18n("Cannot configure KPilot right now (KPilot's UI is already busy)."));
01024         }
01025         return;
01026     }
01027     fAppStatus=UIBusy;
01028     fConfigureKPilotDialogInUse = true;
01029     if (runConfigure(getDaemon(),this))
01030     {
01031         componentUpdate();
01032     }
01033 
01034     fConfigureKPilotDialogInUse = false;
01035     fAppStatus=Normal;
01036 }
01037 
01038 
01039 /* static */ const char *KPilotInstaller::version(int kind)
01040 {
01041     FUNCTIONSETUP;
01042     // I don't think the program title needs to be translated. (ADE)
01043     //
01044     //
01045     if (kind)
01046     {
01047         return "kpilot.cc";
01048     }
01049     else
01050     {
01051         return "KPilot v" KPILOT_VERSION;
01052     }
01053 }
01054 
01055 // Command line options descriptions.
01056 //
01057 //
01058 //
01059 //
01060 static KCmdLineOptions kpilotoptions[] = {
01061     {"s", 0, 0},
01062     {"setup",
01063         I18N_NOOP("Setup the Pilot device, conduits and other parameters"),
01064         0L},
01065 #ifdef DEBUG
01066     {"debug <level>", I18N_NOOP("Set debugging level"), "0"},
01067 #endif
01068     KCmdLineLastOption
01069 };
01070 
01071 
01072 
01073 
01074 // "Regular" mode == 0
01075 // setup mode == 's'
01076 //
01077 // This is only changed by the --setup flag --
01078 // kpilot still does a setup the first time it is run.
01079 //
01080 //
01081 KPilotConfig::RunMode run_mode = KPilotConfig::Normal;
01082 
01083 
01084 
01085 int main(int argc, char **argv)
01086 {
01087     FUNCTIONSETUP;
01088 
01089     KAboutData about("kpilot", I18N_NOOP("KPilot"),
01090         KPILOT_VERSION,
01091         "KPilot - HotSync software for KDE\n\n",
01092         KAboutData::License_GPL,
01093         "(c) 1998-2000,2001, Dan Pilone (c) 2000-2006, Adriaan de Groot",
01094         0L,
01095         "http://www.kpilot.org/"
01096         );
01097     about.addAuthor("Dan Pilone",
01098         I18N_NOOP("Project Leader"),
01099         "pilone@slac.com" );
01100     about.addAuthor("Adriaan de Groot",
01101         I18N_NOOP("Maintainer"),
01102         "groot@kde.org", "http://www.kpilot.org/");
01103     about.addAuthor("Reinhold Kainhofer",
01104         I18N_NOOP("Core and conduits developer"), "reinhold@kainhofer.com", "http://reinhold.kainhofer.com/Linux/");
01105     about.addAuthor("Jason 'vanRijn' Kasper",
01106         I18N_NOOP("Core and conduits developer"),
01107         "vR@movingparts.net", "http://movingparts.net/");
01108     about.addCredit("Preston Brown", I18N_NOOP("VCal conduit"));
01109     about.addCredit("Greg Stern", I18N_NOOP("Abbrowser conduit"));
01110     about.addCredit("Chris Molnar", I18N_NOOP("Expenses conduit"));
01111     about.addCredit("Jörn Ahrens", I18N_NOOP("Notepad conduit, Bugfixer"));
01112     about.addCredit("Heiko Purnhagen", I18N_NOOP("Bugfixer"));
01113     about.addCredit("Jörg Habenicht", I18N_NOOP("Bugfixer"));
01114     about.addCredit("Martin Junius",
01115         I18N_NOOP("XML GUI"),
01116         "mj@m-j-s.net", "http://www.m-j-s.net/kde/");
01117     about.addCredit("David Bishop",
01118         I18N_NOOP(".ui files"));
01119     about.addCredit("Aaron J. Seigo",
01120         I18N_NOOP("Bugfixer, coolness"));
01121     about.addCredit("Bertjan Broeksema", 
01122         I18N_NOOP("VCalconduit state machine, CMake"));
01123 
01124     KCmdLineArgs::init(argc, argv, &about);
01125     KCmdLineArgs::addCmdLineOptions(kpilotoptions, "kpilot");
01126     KUniqueApplication::addCmdLineOptions();
01127     KCmdLineArgs *p = KCmdLineArgs::parsedArgs();
01128 
01129 #ifdef DEBUG
01130     KPilotConfig::getDebugLevel(p);
01131 #endif
01132 
01133 
01134     if (!KUniqueApplication::start())
01135     {
01136         return 0;
01137     }
01138     KUniqueApplication a(true, true);
01139 
01140 
01141     if (p->isSet("setup"))
01142     {
01143         run_mode = KPilotConfig::ConfigureKPilot;
01144     }
01145     else if (KPilotSettings::configVersion() < KPilotConfig::ConfigurationVersion)
01146     {
01147         kdWarning() << ": KPilot configuration version "
01148             << KPilotConfig::ConfigurationVersion
01149             << " newer than stored version "
01150             << KPilotSettings::configVersion() << endl;
01151         // Only force a reconfigure and continue if the
01152         // user is expecting normal startup. Otherwise,
01153         // do the configuration they're explicitly asking for.
01154         run_mode = KPilotConfig::interactiveUpdate();
01155         if (run_mode == KPilotConfig::Cancel) return 1;
01156     }
01157 
01158 
01159     if ( (run_mode == KPilotConfig::ConfigureKPilot) ||
01160         (run_mode == KPilotConfig::ConfigureAndContinue) ||
01161         (run_mode == KPilotConfig::WizardAndContinue) )
01162     {
01163 #ifdef DEBUG
01164         DEBUGKPILOT << fname
01165             << ": Running setup first."
01166             << " (mode " << run_mode << ")" << endl;
01167 #endif
01168         PilotDaemonDCOP_stub *daemon = new PilotDaemonDCOP_stub("kpilotDaemon","KPilotDaemonIface");
01169         bool r = false;
01170         if (run_mode == KPilotConfig::WizardAndContinue)
01171         {
01172             r = ( runWizard(*daemon,0L) == OK );
01173         }
01174         else
01175         {
01176             r = runConfigure(*daemon,0L);
01177         }
01178         delete daemon;
01179         if (!r) return 1;
01180         // User expected configure only.
01181         if (run_mode == KPilotConfig::ConfigureKPilot)
01182         {
01183             return 0;
01184         }
01185     }
01186 
01187     if (KPilotSettings::configVersion() < KPilotConfig::ConfigurationVersion)
01188     {
01189         kdWarning() << k_funcinfo <<
01190             ": Is still not configured for use." << endl;
01191         KPilotConfig::sorryVersionOutdated( KPilotSettings::configVersion());
01192         return 1;
01193     }
01194 
01195 
01196     KPilotInstaller *tp = new KPilotInstaller();
01197 
01198     if (tp->status() == KPilotInstaller::Error)
01199     {
01200         KPILOT_DELETE(tp);
01201         return 1;
01202     }
01203 
01204     QTimer::singleShot(0,tp,SLOT(startDaemonIfNeeded()));
01205 
01206     KGlobal::dirs()->addResourceType("pilotdbs",
01207         CSL1("share/apps/kpilot/DBBackup"));
01208     tp->show();
01209     a.setMainWidget(tp);
01210     DEBUGKPILOT << fname << ": MINIICON = " << a.miniIconName() << endl;
01211     return a.exec();
01212 }
01213 
01214 
KDE Home | KDE Accessibility Home | Description of Access Keys