kpilot Library API Documentation

MultiDB-conduit.cc

00001 /* MultiDB-conduit.cc  MultiDB-Conduit for syncing KPilot and KOrganizer
00002 **
00003 ** Copyright (C) 1998-2001 Dan Pilone
00004 ** Copyright (C) 1998-2000 Preston Brown
00005 ** Copyright (C) 1998 Herwin-Jan Steehouwer
00006 ** Copyright (C) 2001 Cornelius Schumacher
00007 ** Copyright (C) 2002 by Reinhold Kainhofer
00008 **
00009 ** This file is part of the MultiDB conduit, a conduit for KPilot that
00010 ** synchronises the Pilot's MultiDB application with the outside world,
00011 ** which currently means KOrganizer.
00012 */
00013 
00014 /*
00015 ** This program is free software; you can redistribute it and/or modify
00016 ** it under the terms of the GNU General Public License as published by
00017 ** the Free Software Foundation; either version 2 of the License, or
00018 ** (at your option) any later version.
00019 **
00020 ** This program is distributed in the hope that it will be useful,
00021 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00022 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00023 ** GNU General Public License for more details.
00024 **
00025 ** You should have received a copy of the GNU General Public License
00026 ** along with this program in a file called COPYING; if not, write to
00027 ** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00028 ** MA 02111-1307, USA.
00029 */
00030 
00031 #include "options.h"
00032 
00033 #if QT_VERSION < 300
00034 #include <qmsgbox.h>
00035 #else
00036 #include <qmessagebox.h>
00037 #endif
00038 
00039 #include <unistd.h>
00040 #include <qtimer.h>
00041 #include <kconfig.h>
00042 #include <kmessagebox.h>
00043 
00044 #include <pilotUser.h>
00045 #include "pilotRecord.h"
00046 #include "pilotSerialDatabase.h"
00047 #include "MultiDB-conduit.h"
00048 #include "DatabaseAction.h"
00049 
00050 using namespace KCal;
00051 
00052 static const char *MultiDB_conduit_id = "$Id: MultiDB-conduit.cc,v 1.5.4.1 2003/03/12 23:31:10 adridg Exp $";
00053 
00054 
00055 
00056 MultiDBConduit::MultiDBConduit(KPilotDeviceLink *d,     const char *n,  const QStringList &l, SyncTypeList_t *tps) : ConduitAction(d,n,l), dbases(), fCurrentDatabase(), fBackupDatabase() {
00057         FUNCTIONSETUP;
00058         (void)MultiDB_conduit_id;
00059         dbnr=0;
00060         synctypes=tps;
00061 }
00062 
00063 void MultiDBConduit::cleanup() {
00064         FUNCTIONSETUP;
00065         
00066         if (!fConfig) return;
00067         
00068         KConfigGroupSaver cfgs(fConfig, conduitSettingsGroup());
00069         fConfig->writeEntry(conduitSettingsGroup(), dbases);
00070         cleanupDB();
00071 }
00072 
00073 void MultiDBConduit::cleanupDB() {
00074         FUNCTIONSETUP;
00075         KPILOT_DELETE(fCurrentDatabase);
00076         KPILOT_DELETE(fBackupDatabase);
00077 }
00078 
00079 // if false is returned, the database will be skipped, so use the return value!!!
00080 bool MultiDBConduit::preSyncAction(DBSyncInfo*dbinfo) {
00081         FUNCTIONSETUP;
00082         switch (dbinfo->syncaction) {
00083                 case st_ask:
00084                 case st_ignore:
00085                 case st_backup:
00086                         return false;
00087                         break;
00088         }
00089         return true;
00090 }
00091 
00092 void MultiDBConduit::finishedDB() {
00093         QTimer::singleShot(0, this, SLOT(syncNextDB()));
00094 };
00095 void MultiDBConduit::syncNextRecord() {
00096         QTimer::singleShot(0, this, SLOT(finishedDB()));
00097 };
00098 
00099 
00100 void MultiDBConduit::syncNextDB() {
00101         FUNCTIONSETUP;
00102         DBInfo dbinfo;
00103         KPilotUser*usr;
00104         // just to make sure
00105         cleanupDB();
00106         if (fHandle->getNextDatabase(++dbnr, &dbinfo/*, cardno*/)<=0) {
00107                 // no more databases available, so cleanup
00108                 QTimer::singleShot(0, this, SLOT(cleanup()));
00109                 return;
00110         }
00111         
00112         KConfigGroupSaver cfgs(fConfig, conduitSettingsGroup());
00113         // db could be opened, so sync, sync sync...
00114         if (!fConfig) {
00115                 kdWarning() << k_funcinfo <<": No configuration set for conduit. Skipping database "<<dbinfo.name<<"..."<<endl;
00116                 goto skip;
00117         }
00118                 
00119         // if creator and/or type don't match, go to next db
00120         if (!isCorrectDBTypeCreator(dbinfo)) goto skip;
00121         // read config entry for the db, will ask if needed. if user cancels, just skip this database...
00122         if (!GetSyncType(dbinfo, &syncinfo)) goto skip;
00123         
00124         dbases.append(dbinfo.name);
00125 #ifdef DEBUG
00126         DEBUGCONDUIT << fname << ": Using file " << syncinfo.filename << " to sync the palm database "<< dbinfo.name << endl;
00127 #endif
00128                 
00129         // preSyncAction should initialize the custom databases/files for the specific action chosen for this db
00130         if (!preSyncAction(&syncinfo)) {
00131 #ifdef DEBUG
00132                 DEBUGCONDUIT << "Error initializing the databases for "<<dbinfo.name<<endl;
00133 #endif
00134                 emit logError(i18n("Unable to initialize the database: ")+dbinfo.name);
00135                 goto error;
00136         }
00137 
00138         usr=fHandle->getPilotUser();
00139         fFullSync |= (syncinfo.synctype==SYNC_FULL) || ( (usr->getLastSyncPC()!=(unsigned long)gethostid()) && fConfig->readBoolEntry(MultiDBConduitFactory::fullSyncOnPCChange, true));
00140         
00141 
00142         // open the db on palm, backup db on harddisk and the calendar file
00143         fBackupDatabase = new PilotLocalDatabase(dbinfo.name);
00144         if (!fBackupDatabase) goto error;
00145         
00146         if (!fBackupDatabase->isDBOpen()) {
00147 #ifdef DEBUG
00148                 DEBUGCONDUIT<<"Backup databse "<<fBackupDatabase->dbPathName()<<" could not be opened. Will fetch a copy from the palm and do a full sync"<<endl;
00149 #endif
00150                 struct DBInfo dbinfo;
00151                 char nm[50];
00152                 strncpy(&nm[0], &dbinfo.name[0], sizeof(nm));
00153                 if (fHandle->findDatabase(&nm[0], &dbinfo)<0 ){
00154 #ifdef DEBUG
00155                         DEBUGCONDUIT<<fname<<": Could not get DBInfo for "<<nm<<"! Skipping databse"<<endl;
00156 #endif
00157                         goto error;
00158                 }
00159                 dbinfo.flags &= ~dlpDBFlagOpen;
00160                 if (!fHandle->retrieveDatabase(fBackupDatabase->dbPathName(), &dbinfo) ) goto error;
00161                 KPILOT_DELETE(fBackupDatabase);
00162                 fBackupDatabase=new PilotLocalDatabase(dbinfo.name);
00163                 if (!fBackupDatabase || ! fBackupDatabase->isDBOpen() ) goto error;
00164                 fFullSync=true;
00165         }
00166 
00167         fCurrentDatabase = new PilotSerialDatabase(pilotSocket(), dbinfo.name, this, dbinfo.name );
00168         
00169         // error messages if any of them could not be loaded
00170         if (!fCurrentDatabase || !fBackupDatabase || !fCurrentDatabase->isDBOpen() || !fBackupDatabase->isDBOpen()) {
00171                 emit logError(i18n("Couldn't open the calendar databases."));
00172                 goto skip;
00173         }
00174 
00175 
00176         // Start the sync by emitting syncRecord()
00177         QTimer::singleShot(0,this,SLOT(syncNextRecord()));
00178         return;
00179         
00180 error:
00181         emit logError(i18n("Sync failed for database: ")+dbinfo.name);
00182 skip:
00183         QTimer::singleShot(0, this, SLOT(syncNextDB()));
00184         return;
00185 }
00186 
00187 
00188 bool MultiDBConduit::GetSyncType(DBInfo dbinfo, DBSyncInfo*syncinfo) {
00189         fConfig->setGroup(dbinfo.name);
00190         syncinfo->set(dbinfo.name,
00191                 fConfig->readNumEntry(getSyncTypeEntry(), st_ask),
00192                 fConfig->readEntry(getSyncFileEntry()));
00193         if (syncinfo->syncaction!=st_ask) return true;
00194         
00195         while (true) { // loop until the user either selects a valid sync method or skips the db
00196                 // if sync type is set to st_ask, display the settings dialog...
00197                 DBSettings*actiondlg=new DBSettings(0, "dbsettings", syncinfo, synctypes, false, false); // grayed out items
00198                 int dlgres=actiondlg->exec();
00199                 // we can dispose of the dialog now (we could also keep the dialog, just in case we have to
00200                 // display it again, but then I have no idea when to delete it...
00201                 delete actiondlg;
00202                 if (dlgres==QDialog::Accepted ) {
00203                         // write out the new settings to the config file and return true to proceed with syncing
00204                         fConfig->writeEntry(getSyncTypeEntry(), syncinfo->syncaction);
00205                         fConfig->writeEntry(getSyncFileEntry(), syncinfo->filename);
00206                         if (syncinfo->syncaction!=st_ask) return true;
00207                 }
00208                 // the dialog was cancelled, so display a message box...
00209                 if (KMessageBox::warningContinueCancel (0, i18n("You did not select a "
00210                                 "sync method for the database. If you continue, the database will be "
00211                                 "skipped during this sync. If you cancel, you will be returned to the "
00212                                 "previous dialog."),
00213                                 i18n("&Continue"), KStdGuiItem::cont(), "noEmptySyncSettingWarning") ) {
00214                         return false;
00215                 }
00216         }
00217         return false;
00218 }
00219 
00220 
00221 
00222 /* virtual */ bool MultiDBConduit::exec() {
00223         FUNCTIONSETUP;
00224 
00225         if (!fConfig) {
00226                 kdWarning() << k_funcinfo <<": No configuration set for conduit. SKIPPING..."<<endl;
00227                 return false;
00228         }
00229 
00230         KConfigGroupSaver cfgs(fConfig, conduitSettingsGroup());
00231         
00232         dbases=fConfig->readListEntry(settingsFileList());
00233         conflictResolution = fConfig->readNumEntry(MultiDBConduitFactory::conflictResolution);
00234         archive = fConfig->readBoolEntry(MultiDBConduitFactory::archive);
00235         
00236                 #ifdef DEBUG
00237                 DEBUGCONDUIT<<k_funcinfo<<": starting sync with syncNextDB "<<endl;
00238                 #endif
00239         QTimer::singleShot(0, this, SLOT(syncNextDB()));
00240         
00241         // OLD CODE: BAD RESPONSE TIME...
00242 /*      // Go through all cards on the palm
00243         int cardno=-1;
00244         DBInfo dbinfo;
00245 //      CardInfo cardinfo;
00246 //      while (dlp_ReadStorageInfo(pilotSocket(), ++cardno, &cardinfo)>0) {
00247                 // go through databases
00248                 int dbnr=-1;
00249                 while (fHandle->getNextDatabase(++dbnr, &dbinfo)>0) {
00250                         if (!isCorrectDBTypeCreator(dbinfo)) continue; // if creator and/or type don't match, go to next db
00251                         // read config entry for the db, will also ask if needed
00252                         // if the user cancels, just skip this database...
00253                         if (!GetSyncType(dbinfo, &syncinfo)) continue;
00254                         strl << dbinfo.name;
00255                         fDatabase = new PilotSerialDatabase(pilotSocket(), dbinfo.name, this, dbinfo.name );
00256                         if (!fDatabase || !fDatabase->isDBOpen()) {
00257                                 kdWarning() << k_funcinfo << ": Couldn't open database "<< dbinfo.name <<"."<< endl;
00258                                 KPILOT_DELETE(fDatabase);
00259 //                              emit syncDone(this);
00260                                 continue;
00261                         }
00262 
00263                         if (isTest()) {
00264                                 // Nothing: the MultiDB conduit doesn't have a test mode.
00265                         } else if (isBackup()) {
00266                                 doBackup();
00267                                 fDatabase->resetSyncFlags();
00268                         } else {
00269                                 doSync();
00270                                 fDatabase->resetSyncFlags();
00271                         }
00272 
00273                         KPILOT_DELETE(fDatabase);
00274                 } // end walk through dbs
00275 //      } // end walp through cards
00276         // cardno and dbnr will contain the nr of cards and the nr of dbs on the last card
00277         fConfig->writeEntry(settingsFileList(), strl);
00278         emit syncDone(this);*/
00279         return true;
00280 }
00281 
00282 // $Log: MultiDB-conduit.cc,v $
00283 // Revision 1.5.4.1  2003/03/12 23:31:10  adridg
00284 // CVS_SILENT: FSF address change
00285 //
00286 // Revision 1.5  2002/08/23 22:59:29  kainhofe
00287 // Implemented Adriaan's change 'signal: void exec()' -> 'bool exec()' for "my" conduits
00288 //
00289 // Revision 1.4  2002/07/05 00:15:22  kainhofe
00290 // Added KPilotDeviceLink::tickle(), Changelog update, compile fixes
00291 //
00292 // Revision 1.3  2002/04/08 12:56:43  mhunter
00293 // Corrected typographical errors
00294 //
00295 // Revision 1.2  2002/04/07 20:19:48  cschumac
00296 // Compile fixes.
00297 //
00298 // Revision 1.1  2002/04/07 12:09:42  kainhofe
00299 // Initial checkin of the conduit. The gui works mostly, but syncing crashes KPilot...
00300 //
00301 // Revision 1.2  2002/04/07 11:56:19  reinhold
00302 // Last version before moving to KDE CVS
00303 //
00304 // Revision 1.1  2002/04/07 01:03:52  reinhold
00305 // the list of possible actions is now created dynamically
00306 //
00307 // Revision 1.9  2002/04/05 21:17:00  reinhold
00308 // *** empty log message ***
00309 //
00310 // Revision 1.8  2002/03/28 13:47:53  reinhold
00311 // Added the list of synctypes, aboutbox is now directly passed on to the setup dlg (instead of being a static var)
00312 //
00313 // Revision 1.6  2002/03/23 21:46:42  reinhold
00314 // config  dlg works, but the last changes crash the plugin itself
00315 //
00316 // Revision 1.5  2002/03/23 18:21:14  reinhold
00317 // Cleaned up the structure. Works with QTimer instead of loops.
00318 //
00319 // Revision 1.4  2002/03/15 20:43:17  reinhold
00320 // Fixed the crash on loading (member function not defined)...
00321 //
00322 // Revision 1.3  2002/03/10 23:58:32  reinhold
00323 // Made the conduit compile...
00324 //
00325 // Revision 1.2  2002/03/10 16:06:43  reinhold
00326 // Cleaned up the class hierarchy, implemented some more features (should be quite finished now...)
00327 //
00328 // Revision 1.1.1.1  2002/03/09 15:38:45  reinhold
00329 // Initial checin of the  project manager / List manager conduit.
00330 //
00331 //
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sat Oct 18 02:47:14 2003 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001