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 Wed Jul 28 23:57:48 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003