kpilot

kpilot.cc

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