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"