You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
395 lines
11 KiB
395 lines
11 KiB
14 years ago
|
/* KPilot
|
||
|
**
|
||
|
** Copyright (C) 2003 Reinhold Kainhofer <reinhold@kainhofer.com>
|
||
|
**
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
** 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 <options.h>
|
||
|
|
||
|
#include <tqtimer.h>
|
||
13 years ago
|
#include <tqlayout.h>
|
||
14 years ago
|
#include <tqlabel.h>
|
||
12 years ago
|
#include <tdemessagebox.h>
|
||
14 years ago
|
#include <kdialog.h>
|
||
|
#include <ktextedit.h>
|
||
|
#include <kdialogbase.h>
|
||
|
|
||
|
#include <pilotRecord.h>
|
||
|
#include <pilotLocalDatabase.h>
|
||
|
#include <pilotDatabase.h>
|
||
|
#include <pilotSerialDatabase.h>
|
||
|
#include "kpilotConfig.h"
|
||
|
#include "internalEditorAction.h"
|
||
|
|
||
|
#include <pilotAddress.h>
|
||
|
#include <pilotMemo.h>
|
||
|
#include <pilotDateEntry.h>
|
||
|
#include <pilotTodoEntry.h>
|
||
|
|
||
|
#include "khexedit/byteseditinterface.h"
|
||
|
using namespace KHE;
|
||
|
|
||
|
InternalEditorAction::InternalEditorAction(KPilotLink * p) :
|
||
|
SyncAction(p, "internalSync")
|
||
|
{
|
||
|
FUNCTIONSETUP;
|
||
|
}
|
||
|
|
||
|
bool InternalEditorAction::exec()
|
||
|
{
|
||
|
FUNCTIONSETUP;
|
||
|
emit logMessage(i18n("[Internal Editors]"));
|
||
13 years ago
|
fInternalEditorSyncStatus=eSyncStarted;
|
||
14 years ago
|
TQTimer::singleShot(0, this, TQT_SLOT(syncDirtyDB()));
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void InternalEditorAction::syncDirtyDB()
|
||
|
{
|
||
|
FUNCTIONSETUP;
|
||
|
|
||
13 years ago
|
if (fInternalEditorSyncStatus!=eSyncDirtyDB)
|
||
14 years ago
|
{
|
||
13 years ago
|
fInternalEditorSyncStatus=eSyncDirtyDB;
|
||
14 years ago
|
dirtyDBs=KPilotSettings::dirtyDatabases();
|
||
13 years ago
|
emit logMessage(i18n("Databases with changed records: %1").arg(dirtyDBs.join(CSL1(", "))));
|
||
14 years ago
|
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)<<endl;
|
||
|
#endif
|
||
|
// open the local and the serial database and copy every
|
||
|
// changed record from the PC to the handheld
|
||
|
|
||
|
PilotRecord*rec=0L;
|
||
8 years ago
|
PilotLocalDatabase*localDB=new PilotLocalDatabase(*dbIter);
|
||
14 years ago
|
PilotDatabase *serialDB= deviceLink()->database(*dbIter);
|
||
|
if (!localDB->isOpen() || !serialDB->isOpen())
|
||
|
{
|
||
|
emit logError(i18n("Unable to open the serial or local database for %1. "
|
||
13 years ago
|
"Skipping it.").arg(*dbIter));
|
||
14 years ago
|
goto nextDB;
|
||
|
}
|
||
|
while ( (rec=localDB->readNextModifiedRec()) )
|
||
|
{
|
||
|
int id=rec->id();
|
||
|
#ifdef DEBUG
|
||
|
DEBUGKPILOT<<"ID of modified record is "<<id<<endl;
|
||
|
DEBUGKPILOT<<endl<<endl;
|
||
|
#endif
|
||
|
if (id>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 "<<rec->id()<<" with data "<<endl;
|
||
|
DEBUGKPILOT<<rec->data()<<endl;
|
||
|
DEBUGKPILOT<<"-----------------------------------------"<<endl;
|
||
|
#endif
|
||
|
int id=serialDB->writeRecord(rec);
|
||
|
rec->setID(id);
|
||
|
#ifdef DEBUG
|
||
|
DEBUGKPILOT<<"New ID is "<<id<<endl;
|
||
|
DEBUGKPILOT<<endl<<endl<<endl;
|
||
|
#endif
|
||
|
//localDB->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);
|
||
13 years ago
|
localEntry=localAddr.getTextRepresentation(&info,TQt::RichText);
|
||
|
serialEntry=serialAddr.getTextRepresentation(&info,TQt::RichText);
|
||
14 years ago
|
recType=i18n("address");
|
||
|
}
|
||
|
else
|
||
|
if (dbName==CSL1("ToDoDB") && db)
|
||
|
{
|
||
|
PilotToDoInfo info(db);
|
||
|
|
||
|
PilotTodoEntry localTodo(localrec);
|
||
|
PilotTodoEntry serialTodo(serialrec);
|
||
13 years ago
|
localEntry=localTodo.getTextRepresentation(TQt::RichText);
|
||
|
serialEntry=serialTodo.getTextRepresentation(TQt::RichText);
|
||
14 years ago
|
recType=i18n("to-do entry");
|
||
|
}
|
||
|
else
|
||
|
if (dbName==CSL1("MemoDB"))
|
||
|
{
|
||
|
PilotMemo localMemo(localrec);
|
||
|
PilotMemo serialMemo(serialrec);
|
||
13 years ago
|
localEntry=localMemo.getTextRepresentation(TQt::RichText);
|
||
|
serialEntry=serialMemo.getTextRepresentation(TQt::RichText);
|
||
14 years ago
|
recType=i18n("memo");
|
||
|
}
|
||
|
else
|
||
|
if (dbName==CSL1("DatebookDB"))
|
||
|
{
|
||
|
PilotDateInfo info(db);
|
||
|
|
||
|
PilotDateEntry localEvent(localrec);
|
||
|
PilotDateEntry serialEvent(serialrec);
|
||
13 years ago
|
localEntry=localEvent.getTextRepresentation(TQt::RichText);
|
||
|
serialEntry=serialEvent.getTextRepresentation(TQt::RichText);
|
||
14 years ago
|
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?").
|
||
13 years ago
|
arg(recType).arg(id).arg(dbName));
|
||
14 years ago
|
|
||
|
KDialogBase*resdlg=new KDialogBase(0L, "internalresolutiondialog", true,
|
||
13 years ago
|
i18n("Conflict in database %1").arg(*dbIter),
|
||
14 years ago
|
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);
|
||
13 years ago
|
TQGridLayout*layout = new TQGridLayout( page, 1, 1);
|
||
14 years ago
|
|
||
|
TQLabel *label=new TQLabel(dialogText, page);
|
||
13 years ago
|
label->setAlignment( TQLabel::WordBreak );
|
||
13 years ago
|
layout->addMultiCellWidget( label, 0,0, 0,1 );
|
||
14 years ago
|
|
||
13 years ago
|
layout->addItem( new TQSpacerItem( 20, 10, TQSizePolicy::Minimum,
|
||
14 years ago
|
TQSizePolicy::Fixed ), 1, 0 );
|
||
|
|
||
|
if (knownDB)
|
||
|
{
|
||
|
label=new TQLabel(i18n("Entry in KPilot"), page);
|
||
13 years ago
|
layout->addWidget( label, 2,0);
|
||
14 years ago
|
|
||
13 years ago
|
KTextEdit*textBrowser = new KTextEdit(CSL1("<qt>")+localEntry+CSL1("</qt>"), TQString(), page);
|
||
14 years ago
|
textBrowser->setReadOnly(true);
|
||
13 years ago
|
layout->addWidget( textBrowser, 3,0);
|
||
14 years ago
|
|
||
|
label=new TQLabel(i18n("Entry on Handheld"), page);
|
||
13 years ago
|
layout->addWidget( label, 2,1);
|
||
14 years ago
|
|
||
13 years ago
|
textBrowser = new KTextEdit(CSL1("<qt>")+serialEntry+CSL1("</qt>"), TQString(), page);
|
||
14 years ago
|
textBrowser->setReadOnly(true);
|
||
13 years ago
|
layout->addWidget( textBrowser, 3,1);
|
||
14 years ago
|
}
|
||
|
else
|
||
|
{
|
||
|
label=new TQLabel(i18n("Entry in KPilot"), page);
|
||
13 years ago
|
layout->addMultiCellWidget( label, 2,2,0,1);
|
||
14 years ago
|
|
||
|
// 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
|
||
|
{
|
||
13 years ago
|
TQLabel*tmpW = new TQLabel( i18n("To view and edit the record data, please install a hex editor (e.g. khexedit from tdeutils)."), page );
|
||
13 years ago
|
tmpW->setBackgroundMode( TQt::PaletteMid );
|
||
13 years ago
|
tmpW->setAlignment( TQt::AlignHCenter | TQt::AlignVCenter | TQt::WordBreak);
|
||
14 years ago
|
tmpW->setFrameShape( TQFrame::Panel );
|
||
|
tmpW->setFrameShadow( TQFrame::Sunken );
|
||
|
hexEdit = tmpW;
|
||
|
}
|
||
13 years ago
|
layout->addMultiCellWidget( hexEdit, 3,3,0,1);
|
||
14 years ago
|
|
||
|
label=new TQLabel(i18n("Entry on Handheld"), page);
|
||
13 years ago
|
layout->addMultiCellWidget( label, 4,4,0,1);
|
||
14 years ago
|
|
||
|
// 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
|
||
|
{
|
||
13 years ago
|
TQLabel*tmpW = new TQLabel( i18n("To view and edit the record data, please install a hex editor (e.g. khexedit from tdeutils)."), page );
|
||
13 years ago
|
tmpW->setBackgroundMode( TQt::PaletteMid );
|
||
13 years ago
|
tmpW->setAlignment( TQt::AlignHCenter | TQt::AlignVCenter | TQt::WordBreak);
|
||
14 years ago
|
tmpW->setFrameShape( TQFrame::Panel );
|
||
|
tmpW->setFrameShadow( TQFrame::Sunken );
|
||
|
hexEdit = tmpW;
|
||
|
}
|
||
13 years ago
|
layout->addMultiCellWidget( hexEdit, 5,5,0,1);
|
||
14 years ago
|
}
|
||
|
|
||
|
int res=resdlg->exec();
|
||
|
KPILOT_DELETE(resdlg);
|
||
|
|
||
|
return res==KDialogBase::Accepted;
|
||
|
}
|
||
|
|
||
|
|
||
|
void InternalEditorAction::syncFlagsChangedDB()
|
||
|
{
|
||
|
FUNCTIONSETUP;
|
||
13 years ago
|
if (fInternalEditorSyncStatus!=eSyncFlagsChangedDB)
|
||
14 years ago
|
{
|
||
13 years ago
|
fInternalEditorSyncStatus=eSyncFlagsChangedDB;
|
||
14 years ago
|
dirtyDBs=KPilotSettings::flagsChangedDatabases();
|
||
13 years ago
|
emit logMessage(i18n("Databases with changed flags: %1").arg(dirtyDBs.join(CSL1(", "))));
|
||
14 years ago
|
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)<<endl;
|
||
|
#endif
|
||
|
emit logError(i18n("Setting the database flags on the handheld is not yet supported."));
|
||
|
TQTimer::singleShot(0, this, TQT_SLOT(syncAppBlockChangedDB()));
|
||
|
return;
|
||
|
|
||
8 years ago
|
PilotLocalDatabase*localDB=new PilotLocalDatabase(*dbIter);
|
||
14 years ago
|
PilotDatabase *serialDB=deviceLink()->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;
|
||
13 years ago
|
if (fInternalEditorSyncStatus!=eSyncAppBlockChangedDB)
|
||
14 years ago
|
{
|
||
13 years ago
|
fInternalEditorSyncStatus=eSyncAppBlockChangedDB;
|
||
14 years ago
|
dirtyDBs=KPilotSettings::appBlockChangedDatabases();
|
||
13 years ago
|
emit logMessage(i18n("Databases with changed AppBlock: %1").arg(dirtyDBs.join(CSL1(", "))));
|
||
14 years ago
|
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)<<endl;
|
||
|
#endif
|
||
|
|
||
8 years ago
|
PilotLocalDatabase*localDB=new PilotLocalDatabase(*dbIter);
|
||
14 years ago
|
PilotDatabase *serialDB=deviceLink()->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;
|
||
13 years ago
|
fInternalEditorSyncStatus=eSyncFinished;
|
||
14 years ago
|
emit syncDone(this);
|
||
|
}
|
||
|
|
||
|
#include "internalEditorAction.moc"
|