kpilot Library API Documentation

internalEditorAction.cc

00001 /* internalEditorAction.cc                KPilot
00002 **
00003 ** Copyright (C) 2003 by Dan Pilone
00004 ** Written 2003 by Reinhold Kainhofer
00005 **
00006 */
00007 
00008 /*
00009 ** This program is free software; you can redistribute it and/or modify
00010 ** it under the terms of the GNU General Public License as published by
00011 ** the Free Software Foundation; either version 2 of the License, or
00012 ** (at your option) any later version.
00013 **
00014 ** This program is distributed in the hope that it will be useful,
00015 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017 ** GNU General Public License for more details.
00018 **
00019 ** You should have received a copy of the GNU General Public License
00020 ** along with this program in a file called COPYING; if not, write to
00021 ** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00022 ** MA 02111-1307, USA.
00023 */
00024 
00025 /*
00026 ** Bug reports and questions can be sent to kde-pim@kde.org
00027 */
00028 
00029 #include <options.h>
00030 
00031 #include <qtimer.h>
00032 #include <kmessagebox.h>
00033 #include <kdialog.h>
00034 #include <qlayout.h>
00035 #include <qlabel.h>
00036 #include <ktextedit.h>
00037 
00038 #include <pilotRecord.h>
00039 #include <pilotLocalDatabase.h>
00040 #include <pilotDatabase.h>
00041 #include <pilotSerialDatabase.h>
00042 #include "kpilotConfig.h"
00043 #include "internalEditorAction.h"
00044 
00045 #include <pilotAddress.h>
00046 #include <pilotMemo.h>
00047 #include <pilotDateEntry.h>
00048 #include <pilotTodoEntry.h>
00049 
00050 #ifdef USE_KHEXEDIT
00051 #include "khexedit/byteseditinterface.h"
00052 using namespace KHE;
00053 #endif
00054 
00055 InternalEditorAction::InternalEditorAction(KPilotDeviceLink * p, int) :
00056     SyncAction(p, "internalSync")
00057 {
00058     FUNCTIONSETUP;
00059 }
00060 
00061 bool InternalEditorAction::exec()
00062 {
00063     FUNCTIONSETUP;
00064     emit logMessage(i18n("Synchronizing changes by the internal editors of KPilot:"));
00065     fInternalEditorSyncStatus=eSyncStarted;
00066     QTimer::singleShot(0, this, SLOT(syncDirtyDB()));
00067     return true;
00068 }
00069 
00070 void InternalEditorAction::syncDirtyDB()
00071 {
00072     FUNCTIONSETUP;
00073 
00074     if (fInternalEditorSyncStatus!=eSyncDirtyDB)
00075     {
00076         fInternalEditorSyncStatus=eSyncDirtyDB;
00077         dirtyDBs=KPilotConfig::getConfig().getDirtyDatabases();
00078         emit logMessage(i18n("Databases with changed records: %1").arg(dirtyDBs.join(", ")));
00079         dbIter=dirtyDBs.begin();
00080     }
00081     else
00082     {
00083         dbIter++;
00084     }
00085     if (dbIter==dirtyDBs.end())
00086     {
00087         KPilotConfig::getConfig().setDirtyDatabases(QStringList());
00088         KPilotConfig::getConfig().sync();
00089         QTimer::singleShot(0, this, SLOT(syncFlagsChangedDB()));
00090         return;
00091     }
00092 #ifdef DEBUG
00093     DEBUGKPILOT<<"syncDirtyDB for DB "<<(*dbIter)<<endl;
00094 #endif
00095     // open the local and the serial database and copy every
00096     // changed record from the PC to the handheld
00097 
00098     PilotRecord*rec=0L;
00099     PilotLocalDatabase*localDB=new PilotLocalDatabase(*dbIter);
00100     PilotSerialDatabase*serialDB=new PilotSerialDatabase(pilotSocket(), *dbIter);
00101     if (!localDB->isDBOpen() || !serialDB->isDBOpen())
00102     {
00103         emit logError(i18n("Unable to open the serial or local database for %1. "
00104             "Skipping it.").arg(*dbIter));
00105         goto nextDB;
00106     }
00107     while ( (rec=localDB->readNextModifiedRec()) )
00108     {
00109         int id=rec->getID();
00110 #ifdef DEBUG
00111         DEBUGKPILOT<<"ID of modified record is "<<id<<endl;
00112         DEBUGKPILOT<<endl<<endl;
00113 #endif
00114         if (id>0)
00115         {
00116             PilotRecord*serrec=serialDB->readRecordById(id);
00117             if (serrec && (serrec->getAttrib() & dlpRecAttrDirty))
00118             {
00119                 bool kpilotOverrides=queryUseKPilotChanges(*dbIter, id, rec, serrec, localDB);
00120                 if (kpilotOverrides)
00121                     serialDB->writeRecord(rec);
00122                 else
00123                     localDB->writeRecord(serrec);
00124             }
00125             else
00126                 serialDB->writeRecord(rec);
00127         }
00128         else
00129         {
00130 #ifdef DEBUG
00131             DEBUGKPILOT<<"Generating ID for Record "<<rec->getID()<<" with data "<<endl;
00132             DEBUGKPILOT<<rec->getData()<<endl;
00133             DEBUGKPILOT<<"-----------------------------------------"<<endl;
00134 #endif
00135             int id=serialDB->writeRecord(rec);
00136             rec->setID(id);
00137 #ifdef DEBUG
00138             DEBUGKPILOT<<"New ID is "<<id<<endl;
00139             DEBUGKPILOT<<endl<<endl<<endl;
00140 #endif
00141             //localDB->writeRecord(rec);
00142             localDB->writeID(rec);
00143         }
00144         KPILOT_DELETE(rec);
00145     }
00146 
00147 nextDB:
00148     localDB->resetSyncFlags();
00149     KPILOT_DELETE(localDB);
00150     KPILOT_DELETE(serialDB);
00151     QTimer::singleShot(0, this, SLOT(syncDirtyDB()));
00152 }
00153 
00154 bool InternalEditorAction::queryUseKPilotChanges(QString dbName, recordid_t id, PilotRecord*localrec, PilotRecord*serialrec, PilotDatabase*db)
00155 {
00156     FUNCTIONSETUP;
00157     bool knownDB=true;
00158     QString localEntry, serialEntry, recType(i18n("record"));
00159 
00160 
00161     if (dbName=="AddressDB" && db)
00162     {
00163         struct AddressAppInfo fAppInfo;
00164         unsigned char *buffer = new unsigned char[PilotTodoEntry::APP_BUFFER_SIZE];
00165         int appLen = db->readAppBlock(buffer, PilotTodoEntry::APP_BUFFER_SIZE);
00166         unpack_AddressAppInfo(&fAppInfo, buffer, appLen);
00167         delete[] buffer;
00168 
00169         PilotAddress localAddr(fAppInfo, localrec);
00170         PilotAddress serialAddr(fAppInfo, serialrec);
00171         localEntry=localAddr.getTextRepresentation(true);
00172         serialEntry=serialAddr.getTextRepresentation(true);
00173         recType=i18n("address");
00174     }
00175     else
00176     if (dbName=="ToDoDB" && db)
00177     {
00178         struct ToDoAppInfo fAppInfo;
00179         unsigned char *buffer = new unsigned char[PilotTodoEntry::APP_BUFFER_SIZE];
00180         int appLen = db->readAppBlock(buffer, PilotTodoEntry::APP_BUFFER_SIZE);
00181         unpack_ToDoAppInfo(&fAppInfo, buffer, appLen);
00182         delete[] buffer;
00183 
00184         PilotTodoEntry localTodo(fAppInfo, localrec);
00185         PilotTodoEntry serialTodo(fAppInfo, serialrec);
00186         localEntry=localTodo.getTextRepresentation(true);
00187         serialEntry=serialTodo.getTextRepresentation(true);
00188         recType=i18n("todo entry");
00189     }
00190     else
00191     if (dbName=="MemoDB")
00192     {
00193         PilotMemo localMemo(localrec);
00194         PilotMemo serialMemo(serialrec);
00195         localEntry=localMemo.getTextRepresentation(true);
00196         serialEntry=serialMemo.getTextRepresentation(true);
00197         recType=i18n("memo");
00198     }
00199     else
00200     if (dbName=="DatebookDB")
00201     {
00202         PilotDateEntry localEvent(localrec);
00203         PilotDateEntry serialEvent(serialrec);
00204         localEntry=localEvent.getTextRepresentation(true);
00205         serialEntry=serialEvent.getTextRepresentation(true);
00206         recType=i18n("calendar entry");
00207     }
00208     else
00209         knownDB=false;
00210 
00211     QString dialogText(i18n("The %1 with ID %2 of the database \"%3\" was changed "
00212         "on the handheld and in the internal editor. Shall the changes in KPilot be copied to the handheld, and so override the changes there?").
00213         arg(recType).arg(id).arg(dbName));
00214 
00215     KDialogBase*resdlg=new KDialogBase(0L, "internalresolutiondialog", true,
00216         i18n("Conflict in database  %1").arg(*dbIter),
00217         KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true,
00218         i18n("Use KPilot"), i18n("Use Handheld") );
00219     resdlg->setButtonText(KDialogBase::Ok,  i18n("Use &KPilot"));
00220     resdlg->setButtonText(KDialogBase::Cancel, i18n("Use &Handheld"));
00221 
00222     QWidget*page=new QWidget(resdlg);
00223     resdlg->setMainWidget(page);
00224     QGridLayout*layout = new QGridLayout( page, 1, 1);
00225 
00226     QLabel *label=new QLabel(dialogText, page);
00227     label->setAlignment( QLabel::WordBreak );
00228     layout->addMultiCellWidget( label,  0,0, 0,1 );
00229 
00230     layout->addItem( new QSpacerItem( 20, 10, QSizePolicy::Minimum,
00231         QSizePolicy::Fixed ), 1, 0 );
00232 
00233     if (knownDB)
00234     {
00235         label=new QLabel(i18n("Entry in KPilot"), page);
00236         layout->addWidget( label, 2,0);
00237 
00238         KTextEdit*textBrowser = new KTextEdit("<qt>"+localEntry+"</qt>", QString::null, page);
00239         textBrowser->setReadOnly(true);
00240         layout->addWidget( textBrowser, 3,0);
00241 
00242         label=new QLabel(i18n("Entry on Handheld"), page);
00243         layout->addWidget( label, 2,1);
00244 
00245         textBrowser = new KTextEdit("<qt>"+serialEntry+"</qt>", QString::null, page);
00246         textBrowser->setReadOnly(true);
00247         layout->addWidget( textBrowser, 3,1);
00248     }
00249     else
00250     {
00251 #ifdef USE_KHEXEDIT
00252         label=new QLabel(i18n("Entry in KPilot"), page);
00253         layout->addMultiCellWidget( label, 2,2,0,1);
00254 
00255         // directly display the record's data:
00256         QWidget *hexEdit = KHE::createBytesEditWidget( page, "LocalBufferEdit" );
00257         if( hexEdit )
00258         {
00259             KHE::BytesEditInterface* hexEditIf = KHE::bytesEditInterface( hexEdit );
00260             Q_ASSERT( hexEditIf ); // This should not fail!
00261             if( hexEditIf )
00262             {
00263                 hexEditIf->setData( localrec->getData(), localrec->getLen() );
00264 //                  Do we need the following call at all???
00265 //              hexEditIf->setMaxDataSize( localrec->getLen() );
00266                 hexEditIf->setReadOnly( true );
00267             }
00268         }
00269         else
00270         {
00271             QLabel*tmpW = new QLabel( i18n("To view and edit the record data, please install a hex editor (e.g. khexedit from kdeutils)."), page );
00272             tmpW->setBackgroundMode( Qt::PaletteMid );
00273             tmpW->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter | Qt::WordBreak);
00274             tmpW->setFrameShape( QFrame::Panel );
00275             tmpW->setFrameShadow( QFrame::Sunken );
00276             hexEdit = tmpW;
00277         }
00278         layout->addMultiCellWidget( hexEdit, 3,3,0,1);
00279 
00280         label=new QLabel(i18n("Entry on Handheld"), page);
00281         layout->addMultiCellWidget( label, 4,4,0,1);
00282 
00283         // directly display the record's data:
00284         hexEdit = KHE::createBytesEditWidget( page, "SerialBufferEdit" );
00285         if( hexEdit )
00286         {
00287             KHE::BytesEditInterface* hexEditIf = KHE::bytesEditInterface( hexEdit );
00288             Q_ASSERT( hexEditIf ); // This should not fail!
00289             if( hexEditIf )
00290             {
00291                 hexEditIf->setData( serialrec->getData(), serialrec->getLen() );
00292 //                  Do we need the following call at all???
00293 //              hexEditIf->setMaxDataSize( serialrec->getLen() );
00294                 hexEditIf->setReadOnly( true );
00295             }
00296         }
00297         else
00298         {
00299             QLabel*tmpW = new QLabel( i18n("To view and edit the record data, please install a hex editor (e.g. khexedit from kdeutils)."), page );
00300             tmpW->setBackgroundMode( Qt::PaletteMid );
00301             tmpW->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter | Qt::WordBreak);
00302             tmpW->setFrameShape( QFrame::Panel );
00303             tmpW->setFrameShadow( QFrame::Sunken );
00304             hexEdit = tmpW;
00305         }
00306         layout->addMultiCellWidget( hexEdit, 5,5,0,1);
00307 #endif
00308     }
00309 
00310     int res=resdlg->exec();
00311     KPILOT_DELETE(resdlg);
00312 
00313     return res==KDialogBase::Accepted;
00314 }
00315 
00316 
00317 void InternalEditorAction::syncFlagsChangedDB()
00318 {
00319     FUNCTIONSETUP;
00320     if (fInternalEditorSyncStatus!=eSyncFlagsChangedDB)
00321     {
00322         fInternalEditorSyncStatus=eSyncFlagsChangedDB;
00323         dirtyDBs=KPilotConfig::getConfig().getFlagsChangedDatabases();
00324         emit logMessage(i18n("Databases with changed flags: %1").arg(dirtyDBs.join(", ")));
00325         dbIter=dirtyDBs.begin();
00326     }
00327     else
00328     {
00329         dbIter++;
00330     }
00331     if (dbIter==dirtyDBs.end())
00332     {
00333         KPilotConfig::getConfig().setFlagsChangedDatabases(QStringList());
00334         KPilotConfig::getConfig().sync();
00335         QTimer::singleShot(0, this, SLOT(syncAppBlockChangedDB()));
00336         return;
00337     }
00338 
00339 #ifdef DEBUG
00340     DEBUGKPILOT<<"syncFlagsChangedDB for DB "<<(*dbIter)<<endl;
00341 #endif
00342 emit logError(i18n("Setting the database flags on the handheld is not yet supported."));
00343 QTimer::singleShot(0, this, SLOT(syncAppBlockChangedDB()));
00344 return;
00345 
00346     PilotLocalDatabase*localDB=new PilotLocalDatabase(*dbIter);
00347     PilotSerialDatabase*serialDB=new PilotSerialDatabase(pilotSocket(), *dbIter);
00348 
00349     // open the local and the serial database and copy the flags over
00350     // TODO: Implement the copying
00351     // TODO: Is there a way to detect if the flags were changed on the handheld?
00352 
00353     KPILOT_DELETE(localDB);
00354     KPILOT_DELETE(serialDB);
00355     QTimer::singleShot(0, this, SLOT(syncAppBlockChangedDB()));
00356 }
00357 
00358 void InternalEditorAction::syncAppBlockChangedDB()
00359 {
00360     FUNCTIONSETUP;
00361     if (fInternalEditorSyncStatus!=eSyncAppBlockChangedDB)
00362     {
00363         fInternalEditorSyncStatus=eSyncAppBlockChangedDB;
00364         dirtyDBs=KPilotConfig::getConfig().getAppBlockChangedDatabases();
00365         emit logMessage(i18n("Databases with changed AppBlock: %1").arg(dirtyDBs.join(", ")));
00366         dbIter=dirtyDBs.begin();
00367     }
00368     else
00369     {
00370         dbIter++;
00371     }
00372     if (dbIter==dirtyDBs.end())
00373     {
00374         KPilotConfig::getConfig().setAppBlockChangedDatabases(QStringList());
00375         KPilotConfig::getConfig().sync();
00376         QTimer::singleShot(0, this, SLOT(cleanup()));
00377         return;
00378     }
00379 #ifdef DEBUG
00380     DEBUGKPILOT<<"syncAppBlockChangedDB for DB "<<(*dbIter)<<endl;
00381 #endif
00382 
00383     PilotLocalDatabase*localDB=new PilotLocalDatabase(*dbIter);
00384     PilotSerialDatabase*serialDB=new PilotSerialDatabase(pilotSocket(), *dbIter);
00385 
00386     unsigned char*appBlock=new unsigned char[0xFFFF];
00387     int len=localDB->readAppBlock(appBlock, 0xFFFF);
00388     // TODO: Check if the app block was changed on the handheld, and if so, do conflict resolution
00389     serialDB->writeAppBlock(appBlock, len);
00390 
00391     KPILOT_DELETE(localDB);
00392     KPILOT_DELETE(serialDB);
00393     QTimer::singleShot(0, this, SLOT(syncAppBlockChangedDB()));
00394 }
00395 
00396 void InternalEditorAction::cleanup()
00397 {
00398     FUNCTIONSETUP;
00399     fInternalEditorSyncStatus=eSyncFinished;
00400     emit syncDone(this);
00401 }
00402 
00403 #include "internalEditorAction.moc"
KDE Logo
This file is part of the documentation for kpilot Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:36:47 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003