00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
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
00096
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
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
00256 QWidget *hexEdit = KHE::createBytesEditWidget( page, "LocalBufferEdit" );
00257 if( hexEdit )
00258 {
00259 KHE::BytesEditInterface* hexEditIf = KHE::bytesEditInterface( hexEdit );
00260 Q_ASSERT( hexEditIf );
00261 if( hexEditIf )
00262 {
00263 hexEditIf->setData( localrec->getData(), localrec->getLen() );
00264
00265
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
00284 hexEdit = KHE::createBytesEditWidget( page, "SerialBufferEdit" );
00285 if( hexEdit )
00286 {
00287 KHE::BytesEditInterface* hexEditIf = KHE::bytesEditInterface( hexEdit );
00288 Q_ASSERT( hexEditIf );
00289 if( hexEditIf )
00290 {
00291 hexEditIf->setData( serialrec->getData(), serialrec->getLen() );
00292
00293
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
00350
00351
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
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"