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