/* KPilot ** ** Copyright (C) 2003 Reinhold Kainhofer ** */ /* ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program in a file called COPYING; if not, write to ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, ** MA 02110-1301, USA. */ /* ** Bug reports and questions can be sent to kde-pim@kde.org */ #include #include #include #include #include #include #include #include #include #include #include #include #include "kpilotConfig.h" #include "internalEditorAction.h" #include #include #include #include #include "khexedit/byteseditinterface.h" using namespace KHE; InternalEditorAction::InternalEditorAction(KPilotLink * p) : SyncAction(p, "internalSync") { FUNCTIONSETUP; } bool InternalEditorAction::exec() { FUNCTIONSETUP; emit logMessage(i18n("[Internal Editors]")); fInternalEditorSyncStatus=eSyncStarted; TQTimer::singleShot(0, this, TQT_SLOT(syncDirtyDB())); return true; } void InternalEditorAction::syncDirtyDB() { FUNCTIONSETUP; if (fInternalEditorSyncStatus!=eSyncDirtyDB) { fInternalEditorSyncStatus=eSyncDirtyDB; dirtyDBs=KPilotSettings::dirtyDatabases(); emit logMessage(i18n("Databases with changed records: %1").arg(dirtyDBs.join(CSL1(", ")))); dbIter=dirtyDBs.begin(); } else { dbIter++; } if (dbIter==dirtyDBs.end()) { KPilotSettings::setDirtyDatabases(TQStringList()); KPilotConfig::sync(); TQTimer::singleShot(0, this, TQT_SLOT(syncFlagsChangedDB())); return; } #ifdef DEBUG DEBUGKPILOT<<"syncDirtyDB for DB "<<(*dbIter)<database(*dbIter); if (!localDB->isOpen() || !serialDB->isOpen()) { emit logError(i18n("Unable to open the serial or local database for %1. " "Skipping it.").arg(*dbIter)); goto nextDB; } while ( (rec=localDB->readNextModifiedRec()) ) { int id=rec->id(); #ifdef DEBUG DEBUGKPILOT<<"ID of modified record is "<0) { PilotRecord*serrec=serialDB->readRecordById(id); if (serrec && (serrec->isModified()) ) { bool kpilotOverrides=queryUseKPilotChanges(*dbIter, id, rec, serrec, localDB); if (kpilotOverrides) serialDB->writeRecord(rec); else localDB->writeRecord(serrec); } else serialDB->writeRecord(rec); } else { #ifdef DEBUG DEBUGKPILOT<<"Generating ID for Record "<id()<<" with data "<data()<writeRecord(rec); rec->setID(id); #ifdef DEBUG DEBUGKPILOT<<"New ID is "<writeRecord(rec); localDB->updateID(id); } KPILOT_DELETE(rec); } nextDB: localDB->resetSyncFlags(); KPILOT_DELETE(localDB); KPILOT_DELETE(serialDB); TQTimer::singleShot(0, this, TQT_SLOT(syncDirtyDB())); } bool InternalEditorAction::queryUseKPilotChanges(TQString dbName, recordid_t id, PilotRecord*localrec, PilotRecord*serialrec, PilotDatabase*db) { FUNCTIONSETUP; bool knownDB=true; TQString localEntry, serialEntry, recType(i18n("record")); if (dbName==CSL1("AddressDB") && db) { PilotAddressInfo info(db); PilotAddress localAddr(localrec); PilotAddress serialAddr(serialrec); localEntry=localAddr.getTextRepresentation(&info,Qt::RichText); serialEntry=serialAddr.getTextRepresentation(&info,Qt::RichText); recType=i18n("address"); } else if (dbName==CSL1("ToDoDB") && db) { PilotToDoInfo info(db); PilotTodoEntry localTodo(localrec); PilotTodoEntry serialTodo(serialrec); localEntry=localTodo.getTextRepresentation(Qt::RichText); serialEntry=serialTodo.getTextRepresentation(Qt::RichText); recType=i18n("to-do entry"); } else if (dbName==CSL1("MemoDB")) { PilotMemo localMemo(localrec); PilotMemo serialMemo(serialrec); localEntry=localMemo.getTextRepresentation(Qt::RichText); serialEntry=serialMemo.getTextRepresentation(Qt::RichText); recType=i18n("memo"); } else if (dbName==CSL1("DatebookDB")) { PilotDateInfo info(db); PilotDateEntry localEvent(localrec); PilotDateEntry serialEvent(serialrec); localEntry=localEvent.getTextRepresentation(Qt::RichText); serialEntry=serialEvent.getTextRepresentation(Qt::RichText); recType=i18n("calendar entry"); } else { knownDB=false; } TQString dialogText(i18n("The %1 with ID %2 of the database \"%3\" was changed " "on the handheld and in the internal editor. Shall the changes in KPilot be copied to the handheld, and so override the changes there?"). arg(recType).arg(id).arg(dbName)); KDialogBase*resdlg=new KDialogBase(0L, "internalresolutiondialog", true, i18n("Conflict in database %1").arg(*dbIter), KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true, i18n("Use KPilot"), i18n("Use Handheld") ); resdlg->setButtonText(KDialogBase::Ok, i18n("Use &KPilot")); resdlg->setButtonText(KDialogBase::Cancel, i18n("Use &Handheld")); TQWidget*page=new TQWidget(resdlg); resdlg->setMainWidget(page); TQGridLayout*layout = new TQGridLayout( page, 1, 1); TQLabel *label=new TQLabel(dialogText, page); label->setAlignment( TQLabel::WordBreak ); layout->addMultiCellWidget( label, 0,0, 0,1 ); layout->addItem( new TQSpacerItem( 20, 10, TQSizePolicy::Minimum, TQSizePolicy::Fixed ), 1, 0 ); if (knownDB) { label=new TQLabel(i18n("Entry in KPilot"), page); layout->addWidget( label, 2,0); KTextEdit*textBrowser = new KTextEdit(CSL1("")+localEntry+CSL1(""), TQString::null, page); textBrowser->setReadOnly(true); layout->addWidget( textBrowser, 3,0); label=new TQLabel(i18n("Entry on Handheld"), page); layout->addWidget( label, 2,1); textBrowser = new KTextEdit(CSL1("")+serialEntry+CSL1(""), TQString::null, page); textBrowser->setReadOnly(true); layout->addWidget( textBrowser, 3,1); } else { label=new TQLabel(i18n("Entry in KPilot"), page); layout->addMultiCellWidget( label, 2,2,0,1); // directly display the record's data: TQWidget *hexEdit = KHE::createBytesEditWidget( page, "LocalBufferEdit" ); if( hexEdit ) { KHE::BytesEditInterface* hexEditIf = KHE::bytesEditInterface( hexEdit ); Q_ASSERT( hexEditIf ); // This should not fail! if( hexEditIf ) { hexEditIf->setData( localrec->data(), localrec->size() ); // Do we need the following call at all??? // hexEditIf->setMaxDataSize( localrec->getLen() ); hexEditIf->setReadOnly( true ); } } else { TQLabel*tmpW = new TQLabel( i18n("To view and edit the record data, please install a hex editor (e.g. khexedit from kdeutils)."), page ); tmpW->setBackgroundMode( Qt::PaletteMid ); tmpW->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter | Qt::WordBreak); tmpW->setFrameShape( TQFrame::Panel ); tmpW->setFrameShadow( TQFrame::Sunken ); hexEdit = tmpW; } layout->addMultiCellWidget( hexEdit, 3,3,0,1); label=new TQLabel(i18n("Entry on Handheld"), page); layout->addMultiCellWidget( label, 4,4,0,1); // directly display the record's data: hexEdit = KHE::createBytesEditWidget( page, "SerialBufferEdit" ); if( hexEdit ) { KHE::BytesEditInterface* hexEditIf = KHE::bytesEditInterface( hexEdit ); Q_ASSERT( hexEditIf ); // This should not fail! if( hexEditIf ) { hexEditIf->setData( serialrec->data(), serialrec->size() ); // Do we need the following call at all??? // hexEditIf->setMaxDataSize( serialrec->getLen() ); hexEditIf->setReadOnly( true ); } } else { TQLabel*tmpW = new TQLabel( i18n("To view and edit the record data, please install a hex editor (e.g. khexedit from kdeutils)."), page ); tmpW->setBackgroundMode( Qt::PaletteMid ); tmpW->setAlignment( Qt::AlignHCenter | Qt::AlignVCenter | Qt::WordBreak); tmpW->setFrameShape( TQFrame::Panel ); tmpW->setFrameShadow( TQFrame::Sunken ); hexEdit = tmpW; } layout->addMultiCellWidget( hexEdit, 5,5,0,1); } int res=resdlg->exec(); KPILOT_DELETE(resdlg); return res==KDialogBase::Accepted; } void InternalEditorAction::syncFlagsChangedDB() { FUNCTIONSETUP; if (fInternalEditorSyncStatus!=eSyncFlagsChangedDB) { fInternalEditorSyncStatus=eSyncFlagsChangedDB; dirtyDBs=KPilotSettings::flagsChangedDatabases(); emit logMessage(i18n("Databases with changed flags: %1").arg(dirtyDBs.join(CSL1(", ")))); dbIter=dirtyDBs.begin(); } else { dbIter++; } if (dbIter==dirtyDBs.end()) { KPilotSettings::setFlagsChangedDatabases(TQStringList()); KPilotConfig::sync(); TQTimer::singleShot(0, this, TQT_SLOT(syncAppBlockChangedDB())); return; } #ifdef DEBUG DEBUGKPILOT<<"syncFlagsChangedDB for DB "<<(*dbIter)<database(*dbIter); // open the local and the serial database and copy the flags over // TODO: Implement the copying // TODO: Is there a way to detect if the flags were changed on the handheld? KPILOT_DELETE(localDB); KPILOT_DELETE(serialDB); TQTimer::singleShot(0, this, TQT_SLOT(syncAppBlockChangedDB())); } void InternalEditorAction::syncAppBlockChangedDB() { FUNCTIONSETUP; if (fInternalEditorSyncStatus!=eSyncAppBlockChangedDB) { fInternalEditorSyncStatus=eSyncAppBlockChangedDB; dirtyDBs=KPilotSettings::appBlockChangedDatabases(); emit logMessage(i18n("Databases with changed AppBlock: %1").arg(dirtyDBs.join(CSL1(", ")))); dbIter=dirtyDBs.begin(); } else { dbIter++; } if (dbIter==dirtyDBs.end()) { KPilotSettings::setAppBlockChangedDatabases(TQStringList()); KPilotConfig::sync(); TQTimer::singleShot(0, this, TQT_SLOT(cleanup())); return; } #ifdef DEBUG DEBUGKPILOT<<"syncAppBlockChangedDB for DB "<<(*dbIter)<database(*dbIter); unsigned char*appBlock=new unsigned char[0xFFFF]; int len=localDB->readAppBlock(appBlock, 0xFFFF); // TODO: Check if the app block was changed on the handheld, and if so, do conflict resolution serialDB->writeAppBlock(appBlock, len); KPILOT_DELETE(localDB); KPILOT_DELETE(serialDB); TQTimer::singleShot(0, this, TQT_SLOT(syncAppBlockChangedDB())); } void InternalEditorAction::cleanup() { FUNCTIONSETUP; fInternalEditorSyncStatus=eSyncFinished; emit syncDone(this); } #include "internalEditorAction.moc"