From 66abbed5e08370412b81be1628590898ceeeb604 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sat, 29 May 2021 19:05:31 +0900 Subject: Renaming of files in preparation for code style tools. Signed-off-by: Michele Calgaro --- lib/CMakeLists.txt | 10 +- lib/Makefile.am | 24 +- lib/actionQueue.cc | 172 ------- lib/actionQueue.cpp | 172 +++++++ lib/actions.cc | 137 ------ lib/actions.cpp | 137 ++++++ lib/idmapper.cc | 247 ---------- lib/idmapper.cpp | 247 ++++++++++ lib/idmapperxml.cc | 213 -------- lib/idmapperxml.cpp | 213 ++++++++ lib/idmapping.cc | 89 ---- lib/idmapping.cpp | 89 ++++ lib/kpilotdevicelink.cc | 966 ------------------------------------ lib/kpilotdevicelink.cpp | 966 ++++++++++++++++++++++++++++++++++++ lib/kpilotlink.cc | 272 ---------- lib/kpilotlink.cpp | 272 ++++++++++ lib/kpilotlocallink.cc | 368 -------------- lib/kpilotlocallink.cpp | 368 ++++++++++++++ lib/kpilotlocallink.h | 2 +- lib/options.cc | 157 ------ lib/options.cpp | 157 ++++++ lib/pilot.cc | 264 ---------- lib/pilot.cpp | 264 ++++++++++ lib/pilotAddress.cc | 636 ------------------------ lib/pilotAddress.cpp | 636 ++++++++++++++++++++++++ lib/pilotAppInfo.cc | 77 --- lib/pilotAppInfo.cpp | 77 +++ lib/pilotDatabase.cc | 112 ----- lib/pilotDatabase.cpp | 112 +++++ lib/pilotDateEntry.cc | 478 ------------------ lib/pilotDateEntry.cpp | 478 ++++++++++++++++++ lib/pilotDateEntry.h | 2 +- lib/pilotLocalDatabase.cc | 762 ---------------------------- lib/pilotLocalDatabase.cpp | 762 ++++++++++++++++++++++++++++ lib/pilotMemo.cc | 135 ----- lib/pilotMemo.cpp | 135 +++++ lib/pilotMemo.h | 2 +- lib/pilotRecord.cc | 132 ----- lib/pilotRecord.cpp | 132 +++++ lib/pilotSerialDatabase.cc | 432 ---------------- lib/pilotSerialDatabase.cpp | 432 ++++++++++++++++ lib/pilotSerialDatabase.h | 2 +- lib/pilotTodoEntry.cc | 270 ---------- lib/pilotTodoEntry.cpp | 270 ++++++++++ lib/plugin.cc | 760 ---------------------------- lib/plugin.cpp | 760 ++++++++++++++++++++++++++++ lib/recordConduit.cc | 1145 ------------------------------------------- lib/recordConduit.cpp | 1145 +++++++++++++++++++++++++++++++++++++++++++ lib/syncAction.cc | 512 ------------------- lib/syncAction.cpp | 512 +++++++++++++++++++ 50 files changed, 8357 insertions(+), 8357 deletions(-) delete mode 100644 lib/actionQueue.cc create mode 100644 lib/actionQueue.cpp delete mode 100644 lib/actions.cc create mode 100644 lib/actions.cpp delete mode 100644 lib/idmapper.cc create mode 100644 lib/idmapper.cpp delete mode 100644 lib/idmapperxml.cc create mode 100644 lib/idmapperxml.cpp delete mode 100644 lib/idmapping.cc create mode 100644 lib/idmapping.cpp delete mode 100644 lib/kpilotdevicelink.cc create mode 100644 lib/kpilotdevicelink.cpp delete mode 100644 lib/kpilotlink.cc create mode 100644 lib/kpilotlink.cpp delete mode 100644 lib/kpilotlocallink.cc create mode 100644 lib/kpilotlocallink.cpp delete mode 100644 lib/options.cc create mode 100644 lib/options.cpp delete mode 100644 lib/pilot.cc create mode 100644 lib/pilot.cpp delete mode 100644 lib/pilotAddress.cc create mode 100644 lib/pilotAddress.cpp delete mode 100644 lib/pilotAppInfo.cc create mode 100644 lib/pilotAppInfo.cpp delete mode 100644 lib/pilotDatabase.cc create mode 100644 lib/pilotDatabase.cpp delete mode 100644 lib/pilotDateEntry.cc create mode 100644 lib/pilotDateEntry.cpp delete mode 100644 lib/pilotLocalDatabase.cc create mode 100644 lib/pilotLocalDatabase.cpp delete mode 100644 lib/pilotMemo.cc create mode 100644 lib/pilotMemo.cpp delete mode 100644 lib/pilotRecord.cc create mode 100644 lib/pilotRecord.cpp delete mode 100644 lib/pilotSerialDatabase.cc create mode 100644 lib/pilotSerialDatabase.cpp delete mode 100644 lib/pilotTodoEntry.cc create mode 100644 lib/pilotTodoEntry.cpp delete mode 100644 lib/plugin.cc create mode 100644 lib/plugin.cpp delete mode 100644 lib/recordConduit.cc create mode 100644 lib/recordConduit.cpp delete mode 100644 lib/syncAction.cc create mode 100644 lib/syncAction.cpp (limited to 'lib') diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f340d80..1fae0d7 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -19,11 +19,11 @@ tde_import( libkcal ) ##### kpilot (shared) ########################### tde_add_library( kpilot SHARED AUTOMOC - SOURCES kpilotlibSettings.kcfgc options.cc plugin.cc syncAction.cc - kpilotlink.cc kpilotdevicelink.cc kpilotlocallink.cc actions.cc - actionQueue.cc pilot.cc pilotAppInfo.cc pilotRecord.cc pilotDatabase.cc - pilotLocalDatabase.cc pilotSerialDatabase.cc pilotMemo.cc pilotAddress.cc - pilotDateEntry.cc pilotTodoEntry.cc + SOURCES kpilotlibSettings.kcfgc options.cpp plugin.cpp syncAction.cpp + kpilotlink.cpp kpilotdevicelink.cpp kpilotlocallink.cpp actions.cpp + actionQueue.cpp pilot.cpp pilotAppInfo.cpp pilotRecord.cpp pilotDatabase.cpp + pilotLocalDatabase.cpp pilotSerialDatabase.cpp pilotMemo.cpp pilotAddress.cpp + pilotDateEntry.cpp pilotTodoEntry.cpp LINK tdeui-shared tdecore-shared tdeio-shared tdeabc-shared kcal-shared ${PILOTLINK_LIBRARIES} VERSION 0.0.0 diff --git a/lib/Makefile.am b/lib/Makefile.am index 7864a38..6562f5b 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -17,16 +17,16 @@ INCLUDES = $(PISOCK_INCLUDE) -I$(top_srcdir) $(all_includes) lib_LTLIBRARIES = libkpilot.la libkpilot_la_SOURCES = kpilotlibSettings.kcfgc \ - options.cc plugin.cc syncAction.cc \ - kpilotlink.cc kpilotdevicelink.cc kpilotlocallink.cc \ - actions.cc actionQueue.cc \ - pilot.cc \ - pilotAppInfo.cc pilotRecord.cc pilotDatabase.cc \ - pilotLocalDatabase.cc pilotSerialDatabase.cc \ - pilotMemo.cc \ - pilotAddress.cc \ - pilotDateEntry.cc \ - pilotTodoEntry.cc + options.cpp plugin.cpp syncAction.cpp \ + kpilotlink.cpp kpilotdevicelink.cpp kpilotlocallink.cpp \ + actions.cpp actionQueue.cpp \ + pilot.cpp \ + pilotAppInfo.cpp pilotRecord.cpp pilotDatabase.cpp \ + pilotLocalDatabase.cpp pilotSerialDatabase.cpp \ + pilotMemo.cpp \ + pilotAddress.cpp \ + pilotDateEntry.cpp \ + pilotTodoEntry.cpp libkpilot_la_LDFLAGS = $(PISOCK_LDFLAGS) -no-undefined $(all_libraries) $(KDE_EXTRA_RPATH) $(KDE_RPATH) libkpilot_la_LIBADD = $(PISOCK_LIB) $(LIB_TDEUI) $(LIB_TDEABC) -lkcal $(LIB_TQT) $(LIB_TDECORE) -lDCOP $(LIB_TDEIO) @@ -50,9 +50,9 @@ kde_kcfg_DATA = kpilotlib.kcfg check-local: rm -f FAILED for i in $(srcdir)/*.h ; do \ - ( echo "#include " ; echo "#include \"$$i\"" ; echo "int main(int argc,char **argv){return 0;}" ) > header-test.cc; \ + ( echo "#include " ; echo "#include \"$$i\"" ; echo "int main(int argc,char **argv){return 0;}" ) > header-test.cpp; \ echo "$$i" ; \ - g++ $(all_includes) -I$(top_builddir) -DTQT_THREAD_SUPPORT -c header-test.cc || echo "$$i" >> FAILED; \ + g++ $(all_includes) -I$(top_builddir) -DTQT_THREAD_SUPPORT -c header-test.cpp || echo "$$i" >> FAILED; \ done test ! -e FAILED diff --git a/lib/actionQueue.cc b/lib/actionQueue.cc deleted file mode 100644 index 6936297..0000000 --- a/lib/actionQueue.cc +++ /dev/null @@ -1,172 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** -** This defines the "ActionQueue", which is the pile of actions -** that will occur during a HotSync. -*/ - -/* -** 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 - -#include "actions.h" -#include "plugin.h" - -#include "actionQueue.moc" - - - - -ActionQueue::ActionQueue(KPilotLink *d) : - SyncAction(d,"ActionQueue") - // The string lists have default constructors -{ - FUNCTIONSETUP; -} - -ActionQueue::~ActionQueue() -{ - FUNCTIONSETUP; - clear(); -} - -void ActionQueue::clear() -{ - SyncAction *del = 0L; - while ( (del = nextAction()) ) - { - delete del; - } - - Q_ASSERT(isEmpty()); -} - -void ActionQueue::queueInit() -{ - FUNCTIONSETUP; - - addAction(new WelcomeAction(fHandle)); -} - -void ActionQueue::queueConduits(const TQStringList &l, - const SyncAction::SyncMode &m) -{ - FUNCTIONSETUP; - - // Add conduits here ... - // - // - for (TQStringList::ConstIterator it = l.begin(); - it != l.end(); - ++it) - { - if ((*it).startsWith(CSL1("internal_"))) - { -#ifdef DEBUG - DEBUGKPILOT << fname << - ": Ignoring conduit " << *it << endl; -#endif - continue; - } - -#ifdef DEBUG - DEBUGKPILOT << fname - << ": Creating proxy with mode=" << m.name() << endl; -#endif - ConduitProxy *cp = new ConduitProxy(fHandle,*it,m); - addAction(cp); - } -} - -void ActionQueue::queueCleanup() -{ - addAction(new CleanupAction(fHandle)); -} - -bool ActionQueue::exec() -{ - actionCompleted(0L); - return true; -} - -void ActionQueue::actionCompleted(SyncAction *b) -{ - FUNCTIONSETUP; - - if (b) - { -#ifdef DEBUG - DEBUGKPILOT << fname - << ": Completed action " - << b->name() - << endl; -#endif - delete b; - } - - if (isEmpty()) - { - delayDone(); - return; - } - if ( deviceLink() && (!deviceLink()->tickle()) ) - { - emit logError(i18n("The connection to the handheld " - "was lost. Synchronization cannot continue.")); - clear(); - delayDone(); - return; - } - - SyncAction *a = nextAction(); - - if (!a) - { - WARNINGKPILOT << "NULL action on stack." - << endl; - return; - } - -#ifdef DEBUG - DEBUGKPILOT << fname - << ": Will run action " - << a->name() - << endl; -#endif - - TQObject::connect(a, TQT_SIGNAL(logMessage(const TQString &)), - this, TQT_SIGNAL(logMessage(const TQString &))); - TQObject::connect(a, TQT_SIGNAL(logError(const TQString &)), - this, TQT_SIGNAL(logMessage(const TQString &))); - TQObject::connect(a, TQT_SIGNAL(logProgress(const TQString &, int)), - this, TQT_SIGNAL(logProgress(const TQString &, int))); - TQObject::connect(a, TQT_SIGNAL(syncDone(SyncAction *)), - this, TQT_SLOT(actionCompleted(SyncAction *))); - - // Run the action picked from the queue when we get back - // to the event loop. - TQTimer::singleShot(0,a,TQT_SLOT(execConduit())); -} - diff --git a/lib/actionQueue.cpp b/lib/actionQueue.cpp new file mode 100644 index 0000000..6936297 --- /dev/null +++ b/lib/actionQueue.cpp @@ -0,0 +1,172 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** +** This defines the "ActionQueue", which is the pile of actions +** that will occur during a HotSync. +*/ + +/* +** 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 + +#include "actions.h" +#include "plugin.h" + +#include "actionQueue.moc" + + + + +ActionQueue::ActionQueue(KPilotLink *d) : + SyncAction(d,"ActionQueue") + // The string lists have default constructors +{ + FUNCTIONSETUP; +} + +ActionQueue::~ActionQueue() +{ + FUNCTIONSETUP; + clear(); +} + +void ActionQueue::clear() +{ + SyncAction *del = 0L; + while ( (del = nextAction()) ) + { + delete del; + } + + Q_ASSERT(isEmpty()); +} + +void ActionQueue::queueInit() +{ + FUNCTIONSETUP; + + addAction(new WelcomeAction(fHandle)); +} + +void ActionQueue::queueConduits(const TQStringList &l, + const SyncAction::SyncMode &m) +{ + FUNCTIONSETUP; + + // Add conduits here ... + // + // + for (TQStringList::ConstIterator it = l.begin(); + it != l.end(); + ++it) + { + if ((*it).startsWith(CSL1("internal_"))) + { +#ifdef DEBUG + DEBUGKPILOT << fname << + ": Ignoring conduit " << *it << endl; +#endif + continue; + } + +#ifdef DEBUG + DEBUGKPILOT << fname + << ": Creating proxy with mode=" << m.name() << endl; +#endif + ConduitProxy *cp = new ConduitProxy(fHandle,*it,m); + addAction(cp); + } +} + +void ActionQueue::queueCleanup() +{ + addAction(new CleanupAction(fHandle)); +} + +bool ActionQueue::exec() +{ + actionCompleted(0L); + return true; +} + +void ActionQueue::actionCompleted(SyncAction *b) +{ + FUNCTIONSETUP; + + if (b) + { +#ifdef DEBUG + DEBUGKPILOT << fname + << ": Completed action " + << b->name() + << endl; +#endif + delete b; + } + + if (isEmpty()) + { + delayDone(); + return; + } + if ( deviceLink() && (!deviceLink()->tickle()) ) + { + emit logError(i18n("The connection to the handheld " + "was lost. Synchronization cannot continue.")); + clear(); + delayDone(); + return; + } + + SyncAction *a = nextAction(); + + if (!a) + { + WARNINGKPILOT << "NULL action on stack." + << endl; + return; + } + +#ifdef DEBUG + DEBUGKPILOT << fname + << ": Will run action " + << a->name() + << endl; +#endif + + TQObject::connect(a, TQT_SIGNAL(logMessage(const TQString &)), + this, TQT_SIGNAL(logMessage(const TQString &))); + TQObject::connect(a, TQT_SIGNAL(logError(const TQString &)), + this, TQT_SIGNAL(logMessage(const TQString &))); + TQObject::connect(a, TQT_SIGNAL(logProgress(const TQString &, int)), + this, TQT_SIGNAL(logProgress(const TQString &, int))); + TQObject::connect(a, TQT_SIGNAL(syncDone(SyncAction *)), + this, TQT_SLOT(actionCompleted(SyncAction *))); + + // Run the action picked from the queue when we get back + // to the event loop. + TQTimer::singleShot(0,a,TQT_SLOT(execConduit())); +} + diff --git a/lib/actions.cc b/lib/actions.cc deleted file mode 100644 index 212540f..0000000 --- a/lib/actions.cc +++ /dev/null @@ -1,137 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** Copyright (C) 2006 Adriaan de Groot -** -*/ - -/* -** 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 -#include -#include - -#include - -#include "pilot.h" -#include "pilotUser.h" - -#include "actions.h" - - - -WelcomeAction::WelcomeAction(KPilotLink *p) : - SyncAction(p,"welcomeAction") -{ - FUNCTIONSETUP; -} - -/* virtual */ bool WelcomeAction::exec() -{ - FUNCTIONSETUP; - - addSyncLogEntry(i18n("KPilot %1 HotSync starting...\n") - .arg(TQString::fromLatin1(KPILOT_VERSION))); - emit logMessage( i18n("Using encoding %1 on the handheld.").arg(Pilot::codecName()) ); - emit syncDone(this); - return true; -} - -SorryAction::SorryAction(KPilotLink *p, const TQString &s) : - SyncAction(p,"sorryAction"), - fMessage(s) -{ - if (fMessage.isEmpty()) - { - fMessage = i18n("KPilot is busy and cannot process the " - "HotSync right now."); - } -} - -bool SorryAction::exec() -{ - FUNCTIONSETUP; - - addSyncLogEntry(fMessage); - return delayDone(); -} - -CleanupAction::CleanupAction(KPilotLink *p) : SyncAction(p,"cleanupAction") -{ - FUNCTIONSETUP; -} - -/* virtual */ bool CleanupAction::exec() -{ - FUNCTIONSETUP; - - if (deviceLink()) - { - deviceLink()->endSync( KPilotLink::UpdateUserInfo ); - } - emit syncDone(this); - return true; -} - - -TestLink::TestLink(KPilotLink * p) : - SyncAction(p, "testLink") -{ - FUNCTIONSETUP; - -} - -/* virtual */ bool TestLink::exec() -{ - FUNCTIONSETUP; - - int i; - int dbindex = 0; - int count = 0; - struct DBInfo db; - - addSyncLogEntry(i18n("Testing.\n")); - - while ((i = deviceLink()->getNextDatabase(dbindex,&db)) > 0) - { - count++; - dbindex = db.index + 1; - - DEBUGKPILOT << fname - << ": Read database " << db.name - << " with index " << db.index - << endl; - - // Let the Pilot User know what's happening - openConduit(); - // Let the KDE User know what's happening - // Pretty sure all database names are in latin1. - emit logMessage(i18n("Syncing database %1...") - .arg(Pilot::fromPilot(db.name))); - } - - emit logMessage(i18n("HotSync finished.")); - emit syncDone(this); - return true; -} diff --git a/lib/actions.cpp b/lib/actions.cpp new file mode 100644 index 0000000..212540f --- /dev/null +++ b/lib/actions.cpp @@ -0,0 +1,137 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** Copyright (C) 2006 Adriaan de Groot +** +*/ + +/* +** 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 +#include +#include + +#include + +#include "pilot.h" +#include "pilotUser.h" + +#include "actions.h" + + + +WelcomeAction::WelcomeAction(KPilotLink *p) : + SyncAction(p,"welcomeAction") +{ + FUNCTIONSETUP; +} + +/* virtual */ bool WelcomeAction::exec() +{ + FUNCTIONSETUP; + + addSyncLogEntry(i18n("KPilot %1 HotSync starting...\n") + .arg(TQString::fromLatin1(KPILOT_VERSION))); + emit logMessage( i18n("Using encoding %1 on the handheld.").arg(Pilot::codecName()) ); + emit syncDone(this); + return true; +} + +SorryAction::SorryAction(KPilotLink *p, const TQString &s) : + SyncAction(p,"sorryAction"), + fMessage(s) +{ + if (fMessage.isEmpty()) + { + fMessage = i18n("KPilot is busy and cannot process the " + "HotSync right now."); + } +} + +bool SorryAction::exec() +{ + FUNCTIONSETUP; + + addSyncLogEntry(fMessage); + return delayDone(); +} + +CleanupAction::CleanupAction(KPilotLink *p) : SyncAction(p,"cleanupAction") +{ + FUNCTIONSETUP; +} + +/* virtual */ bool CleanupAction::exec() +{ + FUNCTIONSETUP; + + if (deviceLink()) + { + deviceLink()->endSync( KPilotLink::UpdateUserInfo ); + } + emit syncDone(this); + return true; +} + + +TestLink::TestLink(KPilotLink * p) : + SyncAction(p, "testLink") +{ + FUNCTIONSETUP; + +} + +/* virtual */ bool TestLink::exec() +{ + FUNCTIONSETUP; + + int i; + int dbindex = 0; + int count = 0; + struct DBInfo db; + + addSyncLogEntry(i18n("Testing.\n")); + + while ((i = deviceLink()->getNextDatabase(dbindex,&db)) > 0) + { + count++; + dbindex = db.index + 1; + + DEBUGKPILOT << fname + << ": Read database " << db.name + << " with index " << db.index + << endl; + + // Let the Pilot User know what's happening + openConduit(); + // Let the KDE User know what's happening + // Pretty sure all database names are in latin1. + emit logMessage(i18n("Syncing database %1...") + .arg(Pilot::fromPilot(db.name))); + } + + emit logMessage(i18n("HotSync finished.")); + emit syncDone(this); + return true; +} diff --git a/lib/idmapper.cc b/lib/idmapper.cc deleted file mode 100644 index ebd25aa..0000000 --- a/lib/idmapper.cc +++ /dev/null @@ -1,247 +0,0 @@ -/* -** Copyright (C) 2006 Bertjan Broeksema -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 "idmapper.h" -#include "idmapperxml.h" -#include "options.h" - -#include -#include - -#include -#include - -class IDMapperPrivate -{ -public: - IDMapperPrivate() - { - fXmlSource = 0L; - } - - ~IDMapperPrivate() - { - FUNCTIONSETUP; - - KPILOT_DELETE(fXmlSource); - } - - IDMapperXml *fXmlSource; -}; - -IDMapper::IDMapper() -{ - FUNCTIONSETUP; - - fP = new IDMapperPrivate(); - - TQString dbPath = TDEGlobal::dirs()-> - saveLocation("data", CSL1("kpilot/") ); - TQString dbFile = dbPath + CSL1("mapping.xml"); - - if( !openDatasource( dbFile ) ) - { - DEBUGKPILOT << fname << "Could not open or create xml file." << endl; - } -} - -IDMapper::IDMapper( const TQString &file) -{ - FUNCTIONSETUP; - - fP = new IDMapperPrivate(); - - if( !openDatasource( file ) ) - { - DEBUGKPILOT << fname << "Could not open or create xml file." << endl; - } -} - -IDMapper::~IDMapper() -{ - KPILOT_DELETE(fP); -} - -bool IDMapper::openDatasource( const TQString &file ) -{ - FUNCTIONSETUP; - - fP->fXmlSource = new IDMapperXml( file ); - return fP->fXmlSource->open(); -} - -void IDMapper::registerPCObjectId( const TQString &conduit, const TQString &uid ) -{ - FUNCTIONSETUP; - - IDMapping mapping = IDMapping( conduit ); - mapping.setUid( uid ); - - fP->fXmlSource->addMapping( mapping ); - fP->fXmlSource->save(); -} - -void IDMapper::registerHHObjectId( const TQString &conduit, recordid_t pid ) -{ - FUNCTIONSETUP; - - IDMapping mapping = IDMapping( conduit ); - mapping.setPid( pid ); - - fP->fXmlSource->addMapping( mapping ); - fP->fXmlSource->save(); -} - -TQValueList IDMapper::getPCObjectIds( const TQString &conduit ) -{ - FUNCTIONSETUP; - - TQValueList &mappings = fP->fXmlSource->mappings(); - TQValueList::iterator it; - TQValueList uids; - - DEBUGKPILOT << fname << ": total " << mappings.count() << endl; - - for ( it = mappings.begin(); it != mappings.end(); ++it ) - { - IDMapping &mapping = (*it); - - DEBUGKPILOT << fname << ": mapping.conduit() = " << mapping.conduit() << endl; - DEBUGKPILOT << fname << ": conduit = " << conduit << endl; - - if( (mapping.conduit() == conduit) && !mapping.uid().isNull() ) - { - DEBUGKPILOT << fname << ": mapping.conduit() == conduit" << endl; - uids.append( mapping.uid() ); - } - } - - return uids; -} - -TQValueList IDMapper::getHHObjectIds( const TQString &conduit ) -{ - FUNCTIONSETUP; - - TQValueList &mappings = fP->fXmlSource->mappings(); - TQValueList::iterator it; - TQValueList pids; - - for ( it = mappings.begin(); it != mappings.end(); ++it ) - { - IDMapping &mapping = *it; - DEBUGKPILOT << fname << ": mapping.conduit() = " << mapping.conduit() << endl; - DEBUGKPILOT << fname << ": " << mapping.pid() << endl; - if( mapping.conduit() == conduit && mapping.pid() != 0 ) - { - DEBUGKPILOT << fname << ": mapping.conduit() == conduit" << endl; - pids.append( mapping.pid() ); - } - } - - return pids; -} - -bool IDMapper::hasPCId( const TQString &conduit, recordid_t pid ) -{ - FUNCTIONSETUP; - - TQValueList &mappings = fP->fXmlSource->mappings(); - TQValueList::iterator it; - - for ( it = mappings.begin(); it != mappings.end(); ++it ) - { - IDMapping &mapping = *it; - if( mapping.conduit() == conduit && mapping.pid() == pid ) - { - return !mapping.uid().isNull(); - } - } - - return false; -} - -bool IDMapper::hasHHId( const TQString &conduit, const TQString &uid ) -{ - FUNCTIONSETUP; - - TQValueList &mappings = fP->fXmlSource->mappings(); - TQValueList::iterator it; - - for ( it = mappings.begin(); it != mappings.end(); ++it ) - { - IDMapping &mapping = *it; - if( mapping.conduit() == conduit && mapping.uid() == uid ) - { - return mapping.pid() != 0; - } - } - - return false; -} - -void IDMapper::setHHObjectId( const TQString &conduit, const TQString &uid - , recordid_t pid ) -{ - FUNCTIONSETUP; - - bool modified = false; - - TQValueList &mappings = fP->fXmlSource->mappings(); - TQValueList::iterator it; - - for ( it = mappings.begin(); it != mappings.end(); ++it ) - { - IDMapping &mapping = *it; - if( mapping.conduit() == conduit && mapping.uid() == uid ) - { - mapping.setPid( pid ); - fP->fXmlSource->save(); - modified = true; - } - } -} - -void IDMapper::setPCObjectId( const TQString &conduit, recordid_t pid - , const TQString &uid ) -{ - FUNCTIONSETUP; - - bool modified = false; - - TQValueList &mappings = fP->fXmlSource->mappings(); - TQValueList::iterator it; - - for ( it = mappings.begin(); it != mappings.end(); ++it ) - { - IDMapping &mapping = *it; - if( mapping.conduit() == conduit && mapping.pid() == pid ) - { - mapping.setUid( uid ); - fP->fXmlSource->save(); - modified = true; - } - } -} diff --git a/lib/idmapper.cpp b/lib/idmapper.cpp new file mode 100644 index 0000000..ebd25aa --- /dev/null +++ b/lib/idmapper.cpp @@ -0,0 +1,247 @@ +/* +** Copyright (C) 2006 Bertjan Broeksema +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 "idmapper.h" +#include "idmapperxml.h" +#include "options.h" + +#include +#include + +#include +#include + +class IDMapperPrivate +{ +public: + IDMapperPrivate() + { + fXmlSource = 0L; + } + + ~IDMapperPrivate() + { + FUNCTIONSETUP; + + KPILOT_DELETE(fXmlSource); + } + + IDMapperXml *fXmlSource; +}; + +IDMapper::IDMapper() +{ + FUNCTIONSETUP; + + fP = new IDMapperPrivate(); + + TQString dbPath = TDEGlobal::dirs()-> + saveLocation("data", CSL1("kpilot/") ); + TQString dbFile = dbPath + CSL1("mapping.xml"); + + if( !openDatasource( dbFile ) ) + { + DEBUGKPILOT << fname << "Could not open or create xml file." << endl; + } +} + +IDMapper::IDMapper( const TQString &file) +{ + FUNCTIONSETUP; + + fP = new IDMapperPrivate(); + + if( !openDatasource( file ) ) + { + DEBUGKPILOT << fname << "Could not open or create xml file." << endl; + } +} + +IDMapper::~IDMapper() +{ + KPILOT_DELETE(fP); +} + +bool IDMapper::openDatasource( const TQString &file ) +{ + FUNCTIONSETUP; + + fP->fXmlSource = new IDMapperXml( file ); + return fP->fXmlSource->open(); +} + +void IDMapper::registerPCObjectId( const TQString &conduit, const TQString &uid ) +{ + FUNCTIONSETUP; + + IDMapping mapping = IDMapping( conduit ); + mapping.setUid( uid ); + + fP->fXmlSource->addMapping( mapping ); + fP->fXmlSource->save(); +} + +void IDMapper::registerHHObjectId( const TQString &conduit, recordid_t pid ) +{ + FUNCTIONSETUP; + + IDMapping mapping = IDMapping( conduit ); + mapping.setPid( pid ); + + fP->fXmlSource->addMapping( mapping ); + fP->fXmlSource->save(); +} + +TQValueList IDMapper::getPCObjectIds( const TQString &conduit ) +{ + FUNCTIONSETUP; + + TQValueList &mappings = fP->fXmlSource->mappings(); + TQValueList::iterator it; + TQValueList uids; + + DEBUGKPILOT << fname << ": total " << mappings.count() << endl; + + for ( it = mappings.begin(); it != mappings.end(); ++it ) + { + IDMapping &mapping = (*it); + + DEBUGKPILOT << fname << ": mapping.conduit() = " << mapping.conduit() << endl; + DEBUGKPILOT << fname << ": conduit = " << conduit << endl; + + if( (mapping.conduit() == conduit) && !mapping.uid().isNull() ) + { + DEBUGKPILOT << fname << ": mapping.conduit() == conduit" << endl; + uids.append( mapping.uid() ); + } + } + + return uids; +} + +TQValueList IDMapper::getHHObjectIds( const TQString &conduit ) +{ + FUNCTIONSETUP; + + TQValueList &mappings = fP->fXmlSource->mappings(); + TQValueList::iterator it; + TQValueList pids; + + for ( it = mappings.begin(); it != mappings.end(); ++it ) + { + IDMapping &mapping = *it; + DEBUGKPILOT << fname << ": mapping.conduit() = " << mapping.conduit() << endl; + DEBUGKPILOT << fname << ": " << mapping.pid() << endl; + if( mapping.conduit() == conduit && mapping.pid() != 0 ) + { + DEBUGKPILOT << fname << ": mapping.conduit() == conduit" << endl; + pids.append( mapping.pid() ); + } + } + + return pids; +} + +bool IDMapper::hasPCId( const TQString &conduit, recordid_t pid ) +{ + FUNCTIONSETUP; + + TQValueList &mappings = fP->fXmlSource->mappings(); + TQValueList::iterator it; + + for ( it = mappings.begin(); it != mappings.end(); ++it ) + { + IDMapping &mapping = *it; + if( mapping.conduit() == conduit && mapping.pid() == pid ) + { + return !mapping.uid().isNull(); + } + } + + return false; +} + +bool IDMapper::hasHHId( const TQString &conduit, const TQString &uid ) +{ + FUNCTIONSETUP; + + TQValueList &mappings = fP->fXmlSource->mappings(); + TQValueList::iterator it; + + for ( it = mappings.begin(); it != mappings.end(); ++it ) + { + IDMapping &mapping = *it; + if( mapping.conduit() == conduit && mapping.uid() == uid ) + { + return mapping.pid() != 0; + } + } + + return false; +} + +void IDMapper::setHHObjectId( const TQString &conduit, const TQString &uid + , recordid_t pid ) +{ + FUNCTIONSETUP; + + bool modified = false; + + TQValueList &mappings = fP->fXmlSource->mappings(); + TQValueList::iterator it; + + for ( it = mappings.begin(); it != mappings.end(); ++it ) + { + IDMapping &mapping = *it; + if( mapping.conduit() == conduit && mapping.uid() == uid ) + { + mapping.setPid( pid ); + fP->fXmlSource->save(); + modified = true; + } + } +} + +void IDMapper::setPCObjectId( const TQString &conduit, recordid_t pid + , const TQString &uid ) +{ + FUNCTIONSETUP; + + bool modified = false; + + TQValueList &mappings = fP->fXmlSource->mappings(); + TQValueList::iterator it; + + for ( it = mappings.begin(); it != mappings.end(); ++it ) + { + IDMapping &mapping = *it; + if( mapping.conduit() == conduit && mapping.pid() == pid ) + { + mapping.setUid( uid ); + fP->fXmlSource->save(); + modified = true; + } + } +} diff --git a/lib/idmapperxml.cc b/lib/idmapperxml.cc deleted file mode 100644 index 89fe51d..0000000 --- a/lib/idmapperxml.cc +++ /dev/null @@ -1,213 +0,0 @@ -/* -** Copyright (C) 2006 Bertjan Broeksema -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 "idmapperxml.h" - -#include "options.h" - -IDMapperXml::IDMapperXml( const TQString &file ) : fFile(file) - , fCurrentMapping( 0l ) -{ -} - -IDMapperXml::~IDMapperXml() -{ - FUNCTIONSETUP; -} - -bool IDMapperXml::open() -{ - FUNCTIONSETUP; - - root = doc.createElement( CSL1("mappings") ); - TQDomNode node = doc.createProcessingInstruction(CSL1("xml") - ,CSL1("version=\"1.0\" encoding=\"UTF-8\"")); - - doc.appendChild( node ); - doc.appendChild( root ); - - if( !fFile.exists() ) - { - DEBUGKPILOT << fname << ": Creating " << fFile.name() << endl; - - if( fFile.open( IO_ReadWrite ) ) - { - TQTextStream out( &fFile ); - doc.save( out, 4 ); - fFile.close(); - return true; - } - else - { - DEBUGKPILOT << fname << ": Could not create " << fFile.name() << endl; - return false; - } - } - else - { - DEBUGKPILOT << fname << ": Parsing file " << fFile.name() << endl; - TQXmlSimpleReader reader; - reader.setContentHandler( this ); - - // Make sure that the file is closed after parsing. - bool result = reader.parse( fFile ); - fFile.close(); - - return result; - } -} - -void IDMapperXml::save() -{ - FUNCTIONSETUP; - - DEBUGKPILOT << fname << ": Saving " << fMappings.count() - << " mappings..." << endl; - DEBUGKPILOT << fname << ": "; - - TQValueList::const_iterator it; - for ( it = fMappings.begin(); it != fMappings.end(); ++it ) - { - DEBUGKPILOT << "."; - - IDMapping mapping = (*it); - - DEBUGKPILOT << fname << ": " << mapping.conduit(); - - TQDomElement mappingElement = doc.createElement( CSL1("mapping") ); - mappingElement.setAttribute( CSL1("conduit"), mapping.conduit() ); - - if( !mapping.uid().isNull() ) - { - TQDomElement uidElement = doc.createElement( CSL1("uid") ); - uidElement.setAttribute( CSL1("value"), mapping.uid() ); - mappingElement.appendChild( uidElement ); - } - - if( mapping.pid() != 0 ) - { - TQDomElement uidElement = doc.createElement( CSL1("pid") ); - uidElement.setAttribute( CSL1("value"), mapping.pid() ); - mappingElement.appendChild( uidElement ); - } - - if( !mapping.lastSyncTime().isNull() ) - { - TQDomElement uidElement = doc.createElement( CSL1("pid") ); - uidElement.setAttribute( CSL1("value"), TQString::number( mapping.pid() ) ); - mappingElement.appendChild( uidElement ); - } - - root.appendChild( mappingElement ); - } - - if( fFile.open( IO_ReadWrite ) ) - { - TQTextStream out( &fFile ); - doc.save( out, 4 ); - fFile.close(); - - DEBUGKPILOT << endl << fname << ": finished saving." << endl; - } -} - -void IDMapperXml::addMapping( const IDMapping &mapping ) -{ - FUNCTIONSETUP; - - DEBUGKPILOT << fname << ": " << mapping.conduit() << endl; - - fMappings.append( mapping ); - - DEBUGKPILOT << fname << ": " << fMappings.first().conduit() << endl; -} - -TQValueList& IDMapperXml::mappings() -{ - return fMappings; -} - -bool IDMapperXml::startElement( const TQString &namespaceURI - , const TQString &localName, const TQString &qName - , const TQXmlAttributes &attribs ) -{ - FUNCTIONSETUP; - Q_UNUSED(namespaceURI); - Q_UNUSED(localName); - - if( qName == CSL1("mapping") ) - { - TQString conduit( attribs.value( CSL1("conduit") ) ); - - fCurrentMapping = new IDMapping( conduit ); - } - else if( qName == CSL1("uid") ) - { - fCurrentMapping->setUid( attribs.value( CSL1("value") ) ); - } - else if( qName == CSL1("pid") ) - { - fCurrentMapping->setPid( attribs.value( CSL1("value") ).toULong() ); - } - else if( qName == CSL1("lastsync") ) - { - // NOTE: this isn't very robuust! - // Parses only dates in the form: dd-mm-yyyy hh:mm:ss - TQString date = attribs.value( CSL1("value") ); - int day = date.left(2).toInt(); - int month = date.mid(3,2).toInt(); - int year = date.mid(6, 4).toInt(); - - int hour = date.mid(11,2).toInt(); - int minute = date.mid(14,2).toInt(); - int second = date.mid(17,2).toInt(); - - TQDate tmpDate = TQDate( year, month, day ); - TQTime tmpTime = TQTime( hour, minute, second ); - - fCurrentMapping->setLastSyncTime( TQDateTime( tmpDate, tmpTime ) ); - } - - return true; -} - -bool IDMapperXml::endElement( const TQString &namespaceURI - , const TQString &localName, const TQString &qName ) -{ - FUNCTIONSETUP; - - Q_UNUSED(namespaceURI); - Q_UNUSED(localName); - Q_UNUSED(qName); - - if( qName == CSL1("mapping") ) - { - addMapping( *fCurrentMapping ); - delete fCurrentMapping; - fCurrentMapping = 0l; - } - - return true; -} diff --git a/lib/idmapperxml.cpp b/lib/idmapperxml.cpp new file mode 100644 index 0000000..89fe51d --- /dev/null +++ b/lib/idmapperxml.cpp @@ -0,0 +1,213 @@ +/* +** Copyright (C) 2006 Bertjan Broeksema +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 "idmapperxml.h" + +#include "options.h" + +IDMapperXml::IDMapperXml( const TQString &file ) : fFile(file) + , fCurrentMapping( 0l ) +{ +} + +IDMapperXml::~IDMapperXml() +{ + FUNCTIONSETUP; +} + +bool IDMapperXml::open() +{ + FUNCTIONSETUP; + + root = doc.createElement( CSL1("mappings") ); + TQDomNode node = doc.createProcessingInstruction(CSL1("xml") + ,CSL1("version=\"1.0\" encoding=\"UTF-8\"")); + + doc.appendChild( node ); + doc.appendChild( root ); + + if( !fFile.exists() ) + { + DEBUGKPILOT << fname << ": Creating " << fFile.name() << endl; + + if( fFile.open( IO_ReadWrite ) ) + { + TQTextStream out( &fFile ); + doc.save( out, 4 ); + fFile.close(); + return true; + } + else + { + DEBUGKPILOT << fname << ": Could not create " << fFile.name() << endl; + return false; + } + } + else + { + DEBUGKPILOT << fname << ": Parsing file " << fFile.name() << endl; + TQXmlSimpleReader reader; + reader.setContentHandler( this ); + + // Make sure that the file is closed after parsing. + bool result = reader.parse( fFile ); + fFile.close(); + + return result; + } +} + +void IDMapperXml::save() +{ + FUNCTIONSETUP; + + DEBUGKPILOT << fname << ": Saving " << fMappings.count() + << " mappings..." << endl; + DEBUGKPILOT << fname << ": "; + + TQValueList::const_iterator it; + for ( it = fMappings.begin(); it != fMappings.end(); ++it ) + { + DEBUGKPILOT << "."; + + IDMapping mapping = (*it); + + DEBUGKPILOT << fname << ": " << mapping.conduit(); + + TQDomElement mappingElement = doc.createElement( CSL1("mapping") ); + mappingElement.setAttribute( CSL1("conduit"), mapping.conduit() ); + + if( !mapping.uid().isNull() ) + { + TQDomElement uidElement = doc.createElement( CSL1("uid") ); + uidElement.setAttribute( CSL1("value"), mapping.uid() ); + mappingElement.appendChild( uidElement ); + } + + if( mapping.pid() != 0 ) + { + TQDomElement uidElement = doc.createElement( CSL1("pid") ); + uidElement.setAttribute( CSL1("value"), mapping.pid() ); + mappingElement.appendChild( uidElement ); + } + + if( !mapping.lastSyncTime().isNull() ) + { + TQDomElement uidElement = doc.createElement( CSL1("pid") ); + uidElement.setAttribute( CSL1("value"), TQString::number( mapping.pid() ) ); + mappingElement.appendChild( uidElement ); + } + + root.appendChild( mappingElement ); + } + + if( fFile.open( IO_ReadWrite ) ) + { + TQTextStream out( &fFile ); + doc.save( out, 4 ); + fFile.close(); + + DEBUGKPILOT << endl << fname << ": finished saving." << endl; + } +} + +void IDMapperXml::addMapping( const IDMapping &mapping ) +{ + FUNCTIONSETUP; + + DEBUGKPILOT << fname << ": " << mapping.conduit() << endl; + + fMappings.append( mapping ); + + DEBUGKPILOT << fname << ": " << fMappings.first().conduit() << endl; +} + +TQValueList& IDMapperXml::mappings() +{ + return fMappings; +} + +bool IDMapperXml::startElement( const TQString &namespaceURI + , const TQString &localName, const TQString &qName + , const TQXmlAttributes &attribs ) +{ + FUNCTIONSETUP; + Q_UNUSED(namespaceURI); + Q_UNUSED(localName); + + if( qName == CSL1("mapping") ) + { + TQString conduit( attribs.value( CSL1("conduit") ) ); + + fCurrentMapping = new IDMapping( conduit ); + } + else if( qName == CSL1("uid") ) + { + fCurrentMapping->setUid( attribs.value( CSL1("value") ) ); + } + else if( qName == CSL1("pid") ) + { + fCurrentMapping->setPid( attribs.value( CSL1("value") ).toULong() ); + } + else if( qName == CSL1("lastsync") ) + { + // NOTE: this isn't very robuust! + // Parses only dates in the form: dd-mm-yyyy hh:mm:ss + TQString date = attribs.value( CSL1("value") ); + int day = date.left(2).toInt(); + int month = date.mid(3,2).toInt(); + int year = date.mid(6, 4).toInt(); + + int hour = date.mid(11,2).toInt(); + int minute = date.mid(14,2).toInt(); + int second = date.mid(17,2).toInt(); + + TQDate tmpDate = TQDate( year, month, day ); + TQTime tmpTime = TQTime( hour, minute, second ); + + fCurrentMapping->setLastSyncTime( TQDateTime( tmpDate, tmpTime ) ); + } + + return true; +} + +bool IDMapperXml::endElement( const TQString &namespaceURI + , const TQString &localName, const TQString &qName ) +{ + FUNCTIONSETUP; + + Q_UNUSED(namespaceURI); + Q_UNUSED(localName); + Q_UNUSED(qName); + + if( qName == CSL1("mapping") ) + { + addMapping( *fCurrentMapping ); + delete fCurrentMapping; + fCurrentMapping = 0l; + } + + return true; +} diff --git a/lib/idmapping.cc b/lib/idmapping.cc deleted file mode 100644 index 49a1e33..0000000 --- a/lib/idmapping.cc +++ /dev/null @@ -1,89 +0,0 @@ -/* -** Copyright (C) 2006 Bertjan Broeksema -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 "idmapping.h" - -IDMapping::IDMapping() -{ -} - -IDMapping::IDMapping( const TQString &conduit ) -{ - fConduit = conduit; - fPid = 0; -} - -IDMapping::IDMapping( const IDMapping &m ) -{ - fConduit = m.fConduit; - fUid = m.fUid; - fPid = m.fPid; - fLastSync = m.fLastSync; -} - -IDMapping IDMapping::operator=( const IDMapping &m ) -{ - IDMapping local( m.fConduit ); - local.fUid = m.fUid; - local.fPid = m.fPid; - local.fLastSync = m.fLastSync; - - return local; -} - -void IDMapping::setUid( const TQString &uid ) -{ - fUid = uid; -} - -void IDMapping::setPid( recordid_t pid ) -{ - fPid = pid; -} - -void IDMapping::setLastSyncTime( const TQDateTime &datetime ) -{ - fLastSync = datetime; -} - -TQString IDMapping::conduit() const -{ - return fConduit; -} - -TQString IDMapping::uid() const -{ - return fUid; -} - -recordid_t IDMapping::pid() const -{ - return fPid; -} - -TQDateTime IDMapping::lastSyncTime() const -{ - return fLastSync; -} diff --git a/lib/idmapping.cpp b/lib/idmapping.cpp new file mode 100644 index 0000000..49a1e33 --- /dev/null +++ b/lib/idmapping.cpp @@ -0,0 +1,89 @@ +/* +** Copyright (C) 2006 Bertjan Broeksema +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 "idmapping.h" + +IDMapping::IDMapping() +{ +} + +IDMapping::IDMapping( const TQString &conduit ) +{ + fConduit = conduit; + fPid = 0; +} + +IDMapping::IDMapping( const IDMapping &m ) +{ + fConduit = m.fConduit; + fUid = m.fUid; + fPid = m.fPid; + fLastSync = m.fLastSync; +} + +IDMapping IDMapping::operator=( const IDMapping &m ) +{ + IDMapping local( m.fConduit ); + local.fUid = m.fUid; + local.fPid = m.fPid; + local.fLastSync = m.fLastSync; + + return local; +} + +void IDMapping::setUid( const TQString &uid ) +{ + fUid = uid; +} + +void IDMapping::setPid( recordid_t pid ) +{ + fPid = pid; +} + +void IDMapping::setLastSyncTime( const TQDateTime &datetime ) +{ + fLastSync = datetime; +} + +TQString IDMapping::conduit() const +{ + return fConduit; +} + +TQString IDMapping::uid() const +{ + return fUid; +} + +recordid_t IDMapping::pid() const +{ + return fPid; +} + +TQDateTime IDMapping::lastSyncTime() const +{ + return fLastSync; +} diff --git a/lib/kpilotdevicelink.cc b/lib/kpilotdevicelink.cc deleted file mode 100644 index ecad02a..0000000 --- a/lib/kpilotdevicelink.cc +++ /dev/null @@ -1,966 +0,0 @@ -/* KPilot - ** - ** Copyright (C) 1998-2001 by Dan Pilone - ** Copyright (C) 2003-2004 Reinhold Kainhofer - ** Copyright (C) 2006-2007 Adriaan de Groot - ** Copyright (C) 2007 Jason 'vanRijn' Kasper - ** - */ - -/* - ** This program is free software; you can redistribute it and/or modify - ** it under the terms of the GNU Lesser General Public License as published by - ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. - ** - ** You should have received a copy of the GNU Lesser 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 -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "pilotUser.h" -#include "pilotSysInfo.h" -#include "pilotCard.h" -#include "pilotSerialDatabase.h" -#include "pilotLocalDatabase.h" - -#include "kpilotlink.h" -#include "kpilotdevicelinkPrivate.moc" -#include "kpilotdevicelink.moc" - - -DeviceMap *DeviceMap::mThis = 0L; - - -static inline void startOpenTimer(DeviceCommThread *dev, TQTimer *&t) -{ - if ( !t) - { - t = new TQTimer(dev); - TQObject::connect(t, TQT_SIGNAL(timeout()), dev, TQT_SLOT(openDevice())); - } - // just a single-shot timer. we'll know when to start it again... - t->start(1000, true); -} - -DeviceCommThread::DeviceCommThread(KPilotDeviceLink *d) : - TQThread(), - fDone(true), - fHandle(d), - fOpenTimer(0L), - fSocketNotifier(0L), - fSocketNotifierActive(false), - fWorkaroundUSBTimer(0L), - fPilotSocket(-1), - fTempSocket(-1), - fAcceptedCount(0) -{ - FUNCTIONSETUP; -} - - -DeviceCommThread::~DeviceCommThread() -{ - FUNCTIONSETUPL(2); - close(); - KPILOT_DELETE(fWorkaroundUSBTimer); -} - -void DeviceCommThread::close() -{ - FUNCTIONSETUPL(2); - - KPILOT_DELETE(fWorkaroundUSBTimer); - KPILOT_DELETE(fOpenTimer); - KPILOT_DELETE(fSocketNotifier); - fSocketNotifierActive=false; - - if (fTempSocket != -1) - { - DEBUGKPILOT << fname - << ": device comm thread closing socket: [" - << fTempSocket << "]" << endl; - - pi_close(fTempSocket); - } - - if (fPilotSocket != -1) - { - DEBUGKPILOT << fname - << ": device comm thread closing socket: [" - << fPilotSocket << "]" << endl; - - pi_close(fPilotSocket); - } - - fTempSocket = (-1); - fPilotSocket = (-1); - - DeviceMap::self()->unbindDevice(link()->fRealPilotPath); -} - -void DeviceCommThread::reset() -{ - FUNCTIONSETUP; - - if (link()->fMessages->shouldPrint(Messages::OpenFailMessage)) - { - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogMessage, - i18n("Could not open device: %1 (will retry)") - .arg(link()->pilotPath() ))); - } - - link()->fMessages->reset(); - close(); - - // Timer already deleted by close() call. - startOpenTimer(this,fOpenTimer); - - link()->fLinkStatus = WaitingForDevice; -} - -/** - * This is an asyncronous process. We try to create a socket with the Palm - * and then bind to it (in open()). If we're able to do those 2 things, then - * we do 2 things: we set a timeout timer (which will tell us that X amount of - * time has transpired before we get into the meat of the sync transaction), and - * we also set up a TQSocketNotifier, which will tell us when data is available - * to be read from the Palm socket. If we were unable to create a socket - * and/or bind to the Palm in this method, we'll start our timer again. - */ -void DeviceCommThread::openDevice() -{ - FUNCTIONSETUPL(2); - - bool deviceOpened = false; - - // This transition (from Waiting to Found) can only be - // taken once. - // - if (link()->fLinkStatus == WaitingForDevice) - { - link()->fLinkStatus = FoundDevice; - } - - if (link()->fMessages->shouldPrint(Messages::OpenMessage)) - { - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogMessage, - i18n("Trying to open device %1...") - .arg(link()->fPilotPath))); - } - - // if we're not supposed to be done, try to open the main pilot - // path... - if (!fDone && link()->fPilotPath.length() > 0) - { - DEBUGKPILOT << fname << ": Opening main pilot path: [" - << link()->fPilotPath << "]." << endl; - deviceOpened = open(link()->fPilotPath); - } - - // only try the temp device if our earlier attempt didn't work and the temp - // device is different than the main device, and it's a non-empty - // string - bool tryTemp = !deviceOpened && (link()->fTempDevice.length() > 0) && (link()->fPilotPath != link()->fTempDevice); - - // if we're not supposed to be done, and we should try the temp - // device, try the temp device... - if (!fDone && tryTemp) - { - DEBUGKPILOT << fname << ": Couldn't open main pilot path. " - << "Now trying temp device: [" - << link()->fTempDevice << "]." << endl; - deviceOpened = open(link()->fTempDevice); - } - - // if we couldn't connect, try to connect again... - if (!fDone && !deviceOpened) - { - startOpenTimer(this, fOpenTimer); - } -} - -bool DeviceCommThread::open(const TQString &device) -{ - FUNCTIONSETUPL(2); - - int ret; - int e = 0; - TQString msg; - - if (fTempSocket != -1) - { - pi_close(fTempSocket); - } - fTempSocket = (-1); - - link()->fRealPilotPath - = TDEStandardDirs::realFilePath(device.isEmpty() ? link()->fPilotPath : device); - - if ( !DeviceMap::self()->canBind(link()->fRealPilotPath) ) - { - msg = i18n("Already listening on that device"); - - WARNINGKPILOT << "Pilot Path: [" - << link()->fRealPilotPath << "] already connected." << endl; - WARNINGKPILOT << msg << endl; - - link()->fLinkStatus = PilotLinkError; - - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, msg)); - - return false; - } - - DEBUGKPILOT << fname << ": Trying to create socket." << endl; - - fTempSocket = pi_socket(PI_AF_PILOT, PI_SOCK_STREAM, PI_PF_DLP); - - if (fTempSocket < 0) - { - e = errno; - msg = i18n("Cannot create socket for communicating " - "with the Pilot (%1)").arg(errorMessage(e)); - DEBUGKPILOT << msg << endl; - DEBUGKPILOT << "(" << strerror(e) << ")" << endl; - - link()->fLinkStatus = PilotLinkError; - - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, msg)); - - return false; - } - - DEBUGKPILOT << fname << ": Got socket: [" << fTempSocket << "]" << endl; - - link()->fLinkStatus = CreatedSocket; - - DEBUGKPILOT << fname << ": Binding to path: [" - << link()->fRealPilotPath << "]" << endl; - - ret = pi_bind(fTempSocket, TQFile::encodeName(link()->fRealPilotPath)); - - if (ret < 0) - { - DEBUGKPILOT << fname - << ": pi_bind error: [" - << strerror(errno) << "]" << endl; - - e = errno; - msg = i18n("Cannot open Pilot port \"%1\". ").arg(link()->fRealPilotPath); - - DEBUGKPILOT << msg << endl; - DEBUGKPILOT << "(" << strerror(e) << ")" << endl; - - link()->fLinkStatus = PilotLinkError; - - if (link()->fMessages->shouldPrint(Messages::OpenFailMessage)) - { - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, msg)); - } - - return false; - } - - link()->fLinkStatus = DeviceOpen; - DeviceMap::self()->bindDevice(link()->fRealPilotPath); - - fSocketNotifier = new TQSocketNotifier(fTempSocket, - TQSocketNotifier::Read, this); - TQObject::connect(fSocketNotifier, TQT_SIGNAL(activated(int)), - this, TQT_SLOT(acceptDevice())); - fSocketNotifierActive=true; - - /** - * We _always_ want to set a maximum amount of time that we will wait - * for the sync process to start. In the case where our user - * has told us that he has a funky USB device, set the workaround timeout - * for shorter than normal. - */ - int timeout=20000; - if (link()->fWorkaroundUSB) - { - timeout=5000; - } - - fWorkaroundUSBTimer = new TQTimer(this); - connect(fWorkaroundUSBTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(workaroundUSB())); - fWorkaroundUSBTimer->start(timeout, true); - - return true; -} - -/** - * We've been notified by our TQSocketNotifier that we have data available on the - * socket. Try to go through the remaining steps of the connnection process. - * Note: If we return at all from this before the very end without a successful - * connection, we need to make sure we restart our connection open timer, otherwise - * it won't be restarted. - */ -void DeviceCommThread::acceptDevice() -{ - FUNCTIONSETUP; - - int ret; - - /** - * Our socket notifier should be the only reason that we end up here. - * If we're here without him being active, we have a problem. Try to clean - * up and get out. - */ - if (!fSocketNotifierActive) - { - if (!fAcceptedCount) - { - kdWarning() << k_funcinfo << ": Accidentally in acceptDevice()" - << endl; - } - fAcceptedCount++; - if (fAcceptedCount>10) - { - // Damn the torpedoes - KPILOT_DELETE(fSocketNotifier); - } - return; - } - - if (fSocketNotifier) - { - // fSocketNotifier->setEnabled(false); - fSocketNotifierActive=false; - KPILOT_DELETE(fSocketNotifier); - } - - DEBUGKPILOT << fname << ": Found connection on device: [" - << link()->pilotPath().latin1() << "]." <statusString() - << "] and socket: [" << fTempSocket << "]" << endl; - - ret = pi_listen(fTempSocket, 1); - if (ret < 0) - { - char *s = strerror(errno); - - WARNINGKPILOT << "pi_listen returned: [" << s << "]" << endl; - - // Presumably, strerror() returns things in - // local8Bit and not latin1. - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, - i18n("Cannot listen on Pilot socket (%1)"). - arg(TQString::fromLocal8Bit(s)))); - reset(); - return; - } - - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, TQString(), 10)); - - DEBUGKPILOT << fname << - ": Listening to pilot. Now trying accept..." << endl; - - int timeout = 20; - fPilotSocket = pi_accept_to(fTempSocket, 0, 0, timeout); - - if (fPilotSocket < 0) - { - char *s = strerror(errno); - - WARNINGKPILOT << "pi_accept returned: [" << s << "]" << endl; - - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, i18n("Cannot accept Pilot (%1)") - .arg(TQString::fromLocal8Bit(s)))); - - link()->fLinkStatus = PilotLinkError; - reset(); - return; - } - - DEBUGKPILOT << fname << ": Link accept done." << endl; - - if ((link()->fLinkStatus != DeviceOpen) || (fPilotSocket == -1)) - { - link()->fLinkStatus = PilotLinkError; - WARNINGKPILOT << "Already connected or unable to connect!" << endl; - - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, i18n("Cannot accept Pilot (%1)") - .arg(i18n("already connected")))); - - reset(); - return; - } - - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, TQString(), 30)); - - DEBUGKPILOT << fname << ": doing dlp_ReadSysInfo..." << endl; - - struct SysInfo sys_info; - if (dlp_ReadSysInfo(fPilotSocket, &sys_info) < 0) - { - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, - i18n("Unable to read system information from Pilot"))); - - link()->fLinkStatus=PilotLinkError; - reset(); - return; - } - else - { - DEBUGKPILOT << fname << ": dlp_ReadSysInfo successful..." << endl; - - KPILOT_DELETE(link()->fPilotSysInfo); - link()->fPilotSysInfo = new KPilotSysInfo(&sys_info); - DEBUGKPILOT << fname - << ": RomVersion: [" << link()->fPilotSysInfo->getRomVersion() - << "] Locale: [" << link()->fPilotSysInfo->getLocale() - << "] Product: [" << link()->fPilotSysInfo->getProductID() - << "]" << endl; - } - - // If we've made it this far, make sure our USB workaround timer doesn't fire! - fWorkaroundUSBTimer->stop(); - KPILOT_DELETE(fWorkaroundUSBTimer); - - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, TQString(), 60)); - - KPILOT_DELETE(link()->fPilotUser); - link()->fPilotUser = new KPilotUser; - - DEBUGKPILOT << fname << ": doing dlp_ReadUserInfo..." << endl; - - /* Ask the pilot who it is. And see if it's who we think it is. */ - dlp_ReadUserInfo(fPilotSocket, link()->fPilotUser->data()); - - TQString n = link()->getPilotUser().name(); - DEBUGKPILOT << fname - << ": Read user name: [" << n << "]" << endl; - - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, i18n("Checking last PC..."), 90)); - - /* Tell user (via Pilot) that we are starting things up */ - if ((ret=dlp_OpenConduit(fPilotSocket)) < 0) - { - DEBUGKPILOT << fname - << ": dlp_OpenConduit returned: [" << ret << "]" << endl; - - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, - i18n("Could not read user information from the Pilot. " - "Perhaps you have a password set on the device?"))); - - } - link()->fLinkStatus = AcceptedDevice; - - TQApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, TQString(), 100)); - - DeviceCommEvent * ev = new DeviceCommEvent(EventDeviceReady); - ev->setCurrentSocket(fPilotSocket); - TQApplication::postEvent(link(), ev); - -} - -void DeviceCommThread::workaroundUSB() -{ - FUNCTIONSETUP; - - reset(); -} - -void DeviceCommThread::run() -{ - FUNCTIONSETUP; - fDone = false; - - startOpenTimer(this, fOpenTimer); - - int sleepBetweenPoll = 2; - // keep the thread alive until we're supposed to be done - while (!fDone) - { - TQThread::sleep(sleepBetweenPoll); - } - - close(); - // now sleep one last bit to make sure the pthread inside - // pilot-link (potentially, if it's libusb) is done before we exit - TQThread::sleep(1); - - DEBUGKPILOT << fname << ": comm thread now done..." << endl; -} - -KPilotDeviceLink::KPilotDeviceLink(TQObject * parent, const char *name, - const TQString &tempDevice) : - KPilotLink(parent, name), fLinkStatus(Init), fWorkaroundUSB(false), - fPilotSocket(-1), fTempDevice(tempDevice), fMessages(new Messages(this)), fDeviceCommThread(0L) -{ - FUNCTIONSETUP; - - DEBUGKPILOT << fname - << ": Pilot-link version: [" << PILOT_LINK_NUMBER - << "]" << endl; -} - -KPilotDeviceLink::~KPilotDeviceLink() -{ - FUNCTIONSETUP; - close(); - KPILOT_DELETE(fPilotSysInfo); - KPILOT_DELETE(fPilotUser); - KPILOT_DELETE(fMessages); -} - -/* virtual */bool KPilotDeviceLink::isConnected() const -{ - return fLinkStatus == AcceptedDevice; -} - -/* virtual */bool KPilotDeviceLink::event(TQEvent *e) -{ - FUNCTIONSETUP; - - bool handled = false; - - if ((int)e->type() == EventDeviceReady) - { - DeviceCommEvent* t = static_cast(e); - fPilotSocket = t->currentSocket(); - emit deviceReady( this); - handled = true; - } - else if ((int)e->type() == EventLogMessage) - { - DeviceCommEvent* t = static_cast(e); - emit logMessage(t->message()); - handled = true; - } - else if ((int)e->type() == EventLogError) - { - DeviceCommEvent* t = static_cast(e); - emit logError(t->message()); - handled = true; - } - else if ((int)e->type() == EventLogProgress) - { - DeviceCommEvent* t = static_cast(e); - emit logProgress(t->message(), t->progress()); - handled = true; - } - else - { - handled = KPilotLink::event(e); - } - - return handled; -} - -void KPilotDeviceLink::stopCommThread() -{ - FUNCTIONSETUP; - if (fDeviceCommThread) - { - fDeviceCommThread->setDone(true); - - // try to wait for our thread to finish, but don't - // block the main thread forever - if (fDeviceCommThread->running()) - { - DEBUGKPILOT << fname - << ": comm thread still running. " - << "waiting for it to complete." << endl; - bool done = fDeviceCommThread->wait(5000); - if (!done) - { - DEBUGKPILOT << fname - << ": comm thread still running " - << "after wait(). " - << "going to have to terminate it." - << endl; - // not normally to be done, but we must make sure - // that this device doesn't come back alive - fDeviceCommThread->terminate(); - fDeviceCommThread->wait(); - } - } - - fDeviceCommThread->close(); - - KPILOT_DELETE(fDeviceCommThread); - } -} - -void KPilotDeviceLink::close() -{ - FUNCTIONSETUP; - - stopCommThread(); - - fPilotSocket = (-1); -} - -void KPilotDeviceLink::reset(const TQString & dP) -{ - FUNCTIONSETUP; - - fLinkStatus = Init; - - // Release all resources - // - close(); - fPilotPath = TQString(); - - fPilotPath = dP; - if (fPilotPath.isEmpty()) - fPilotPath = fTempDevice; - if (fPilotPath.isEmpty()) - return; - - reset(); -} - -void KPilotDeviceLink::startCommThread() -{ - FUNCTIONSETUP; - - stopCommThread(); - - if (fTempDevice.isEmpty() && pilotPath().isEmpty()) - { - WARNINGKPILOT << "No point in trying empty device." - << endl; - - TQString msg = i18n("The Pilot device is not configured yet."); - WARNINGKPILOT << msg << endl; - - fLinkStatus = PilotLinkError; - - emit logError(msg); - return; - } - - fDeviceCommThread = new DeviceCommThread(this); - fDeviceCommThread->start(); -} - -void KPilotDeviceLink::reset() -{ - FUNCTIONSETUP; - - fMessages->reset(); - close(); - - checkDevice(); - - fLinkStatus = WaitingForDevice; - - startCommThread(); -} - -void KPilotDeviceLink::checkDevice() -{ - // If the device exists yet doesn't have the right - // permissions, complain and then continue anyway. - // - TQFileInfo fi(fPilotPath); - if (fi.exists()) - { - // If it exists, it ought to be RW already. - // - if (!(fi.isReadable() && fi.isWritable())) - { - emit logError(i18n("Pilot device %1 is not read-write.") - .arg(fPilotPath)); - } - } - else - { - // It doesn't exist, mention this in the log - // (relevant as long as we use only one device type) - // - emit - logError(i18n("Pilot device %1 does not exist. " - "Probably it is a USB device and will appear during a HotSync.") - .arg(fPilotPath)); - // Suppress all normal and error messages about opening the device. - fMessages->block(Messages::OpenMessage | Messages::OpenFailMessage, - true); - } -} - -void KPilotDeviceLink::setTempDevice(const TQString &d) -{ - fTempDevice = d; - DeviceMap::self()->bindDevice(fTempDevice); -} - -/* virtual */bool KPilotDeviceLink::tickle() -{ - // No FUNCTIONSETUP here because it may be called from - // a separate thread. - return pi_tickle(pilotSocket()) >= 0; -} - -/* virtual */void KPilotDeviceLink::addSyncLogEntryImpl(const TQString &entry) -{ - dlp_AddSyncLogEntry(fPilotSocket, - const_cast((const char *)Pilot::toPilot(entry))); -} - -bool KPilotDeviceLink::installFile(const TQString & f, const bool deleteFile) -{ - FUNCTIONSETUP; - - DEBUGKPILOT << fname << ": Installing file " << f << endl; - - if (!TQFile::exists(f)) - return false; - - char buffer[PATH_MAX]; - memset(buffer, 0, PATH_MAX); - strlcpy(buffer, TQFile::encodeName(f), PATH_MAX); - struct pi_file *pf = pi_file_open(buffer); - - if (!f) - { - WARNINGKPILOT << "Cannot open file " << f << endl; - emit logError(i18n - ("Cannot install the file "%1"."). - arg(f)); - return false; - } - - if (pi_file_install(pf, fPilotSocket, 0, 0L) < 0) - { - WARNINGKPILOT << "Cannot pi_file_install " << f << endl; - emit logError(i18n - ("Cannot install the file "%1"."). - arg(f)); - return false; - } - - pi_file_close(pf); - if (deleteFile) - TQFile::remove(f); - - return true; -} - -int KPilotDeviceLink::openConduit() -{ - return dlp_OpenConduit(fPilotSocket); -} - -TQString KPilotDeviceLink::statusString(LinkStatus l) -{ - TQString s= CSL1("KPilotDeviceLink="); - - switch (l) - { - case Init: - s.append(CSL1("Init")); - break; - case WaitingForDevice: - s.append(CSL1("WaitingForDevice")); - break; - case FoundDevice: - s.append(CSL1("FoundDevice")); - break; - case CreatedSocket: - s.append(CSL1("CreatedSocket")); - break; - case DeviceOpen: - s.append(CSL1("DeviceOpen")); - break; - case AcceptedDevice: - s.append(CSL1("AcceptedDevice")); - break; - case SyncDone: - s.append(CSL1("SyncDone")); - break; - case PilotLinkError: - s.append(CSL1("PilotLinkError")); - break; - case WorkaroundUSB: - s.append(CSL1("WorkaroundUSB")); - break; - } - - return s; -} - -TQString KPilotDeviceLink::statusString() const -{ - return statusString(status() ); -} - -void KPilotDeviceLink::endSync(EndOfSyncFlags f) -{ - FUNCTIONSETUP; - - if (UpdateUserInfo == f) - { - getPilotUser().setLastSyncPC((unsigned long) gethostid()); - getPilotUser().setLastSyncDate(time(0)); - - DEBUGKPILOT << fname << ": Writing username " << getPilotUser().name() << endl; - - dlp_WriteUserInfo(pilotSocket(), getPilotUser().data()); - addSyncLogEntry(i18n("End of HotSync\n")); - } - dlp_EndOfSync(pilotSocket(), 0); - KPILOT_DELETE(fPilotSysInfo); - KPILOT_DELETE(fPilotUser); -} - -int KPilotDeviceLink::getNextDatabase(int index, struct DBInfo *dbinfo) -{ - FUNCTIONSETUP; - - pi_buffer_t buf = { 0, 0, 0 }; - int r = dlp_ReadDBList(pilotSocket(), 0, dlpDBListRAM, index, &buf); - if (r >= 0) - { - memcpy(dbinfo, buf.data, sizeof(struct DBInfo)); - } - return r; -} - -// Find a database with the given name. Info about the DB is stored into dbinfo (e.g. to be used later on with retrieveDatabase). -int KPilotDeviceLink::findDatabase(const char *name, struct DBInfo *dbinfo, - int index, unsigned long type, unsigned long creator) -{ - FUNCTIONSETUP; - return dlp_FindDBInfo(pilotSocket(), 0, index, const_cast(name), - type, creator, dbinfo); -} - -bool KPilotDeviceLink::retrieveDatabase(const TQString &fullBackupName, - DBInfo *info) -{ - FUNCTIONSETUP; - - if (fullBackupName.isEmpty() || !info) - { - // Don't even bother trying to convert or retrieve. - return false; - } - - DEBUGKPILOT << fname << ": Writing DB <" << info->name << "> " - << " to " << fullBackupName << endl; - - TQCString encodedName = TQFile::encodeName(fullBackupName); - struct pi_file *f = pi_file_create(encodedName, info); - - if (!f) - { - WARNINGKPILOT << "Failed, unable to create file" << endl; - return false; - } - - if (pi_file_retrieve(f, pilotSocket(), 0, 0L) < 0) - { - WARNINGKPILOT << "Failed, unable to back up database" << endl; - - pi_file_close(f); - return false; - } - - pi_file_close(f); - return true; -} - -KPilotLink::DBInfoList KPilotDeviceLink::getDBList(int cardno, int flags) -{ - bool cont=true; - DBInfoList dbs; - int index=0; - while (cont) - { - pi_buffer_t buf = { 0, 0, 0 }; - pi_buffer_clear(&buf); - // DBInfo*dbi=new DBInfo(); - if (dlp_ReadDBList(pilotSocket(), cardno, flags | dlpDBListMultiple, - index, &buf)<0) - { - cont=false; - } - else - { - DBInfo db_n; - DBInfo *db_it = (DBInfo *)buf.data; - int info_count = buf.used / sizeof(struct DBInfo); - - while (info_count>0) - { - memcpy(&db_n, db_it, sizeof(struct DBInfo)); - ++db_it; - info_count--; - dbs.append(db_n); - } - index=db_n.index+1; - } - } - return dbs; -} - -const KPilotCard *KPilotDeviceLink::getCardInfo(int card) -{ - KPilotCard *cardinfo=new KPilotCard(); - if (dlp_ReadStorageInfo(pilotSocket(), card, cardinfo->cardInfo())<0) - { - WARNINGKPILOT << "Could not get info for card " << card << endl; - - KPILOT_DELETE(cardinfo); - return 0L; - } - return cardinfo; -} - -PilotDatabase *KPilotDeviceLink::database(const TQString &name) -{ - return new PilotSerialDatabase( this, name ); -} - -PilotDatabase *KPilotDeviceLink::database(const DBInfo *info) -{ - return new PilotSerialDatabase( this, info ); -} - diff --git a/lib/kpilotdevicelink.cpp b/lib/kpilotdevicelink.cpp new file mode 100644 index 0000000..ecad02a --- /dev/null +++ b/lib/kpilotdevicelink.cpp @@ -0,0 +1,966 @@ +/* KPilot + ** + ** Copyright (C) 1998-2001 by Dan Pilone + ** Copyright (C) 2003-2004 Reinhold Kainhofer + ** Copyright (C) 2006-2007 Adriaan de Groot + ** Copyright (C) 2007 Jason 'vanRijn' Kasper + ** + */ + +/* + ** This program is free software; you can redistribute it and/or modify + ** it under the terms of the GNU Lesser General Public License as published by + ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. + ** + ** You should have received a copy of the GNU Lesser 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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pilotUser.h" +#include "pilotSysInfo.h" +#include "pilotCard.h" +#include "pilotSerialDatabase.h" +#include "pilotLocalDatabase.h" + +#include "kpilotlink.h" +#include "kpilotdevicelinkPrivate.moc" +#include "kpilotdevicelink.moc" + + +DeviceMap *DeviceMap::mThis = 0L; + + +static inline void startOpenTimer(DeviceCommThread *dev, TQTimer *&t) +{ + if ( !t) + { + t = new TQTimer(dev); + TQObject::connect(t, TQT_SIGNAL(timeout()), dev, TQT_SLOT(openDevice())); + } + // just a single-shot timer. we'll know when to start it again... + t->start(1000, true); +} + +DeviceCommThread::DeviceCommThread(KPilotDeviceLink *d) : + TQThread(), + fDone(true), + fHandle(d), + fOpenTimer(0L), + fSocketNotifier(0L), + fSocketNotifierActive(false), + fWorkaroundUSBTimer(0L), + fPilotSocket(-1), + fTempSocket(-1), + fAcceptedCount(0) +{ + FUNCTIONSETUP; +} + + +DeviceCommThread::~DeviceCommThread() +{ + FUNCTIONSETUPL(2); + close(); + KPILOT_DELETE(fWorkaroundUSBTimer); +} + +void DeviceCommThread::close() +{ + FUNCTIONSETUPL(2); + + KPILOT_DELETE(fWorkaroundUSBTimer); + KPILOT_DELETE(fOpenTimer); + KPILOT_DELETE(fSocketNotifier); + fSocketNotifierActive=false; + + if (fTempSocket != -1) + { + DEBUGKPILOT << fname + << ": device comm thread closing socket: [" + << fTempSocket << "]" << endl; + + pi_close(fTempSocket); + } + + if (fPilotSocket != -1) + { + DEBUGKPILOT << fname + << ": device comm thread closing socket: [" + << fPilotSocket << "]" << endl; + + pi_close(fPilotSocket); + } + + fTempSocket = (-1); + fPilotSocket = (-1); + + DeviceMap::self()->unbindDevice(link()->fRealPilotPath); +} + +void DeviceCommThread::reset() +{ + FUNCTIONSETUP; + + if (link()->fMessages->shouldPrint(Messages::OpenFailMessage)) + { + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogMessage, + i18n("Could not open device: %1 (will retry)") + .arg(link()->pilotPath() ))); + } + + link()->fMessages->reset(); + close(); + + // Timer already deleted by close() call. + startOpenTimer(this,fOpenTimer); + + link()->fLinkStatus = WaitingForDevice; +} + +/** + * This is an asyncronous process. We try to create a socket with the Palm + * and then bind to it (in open()). If we're able to do those 2 things, then + * we do 2 things: we set a timeout timer (which will tell us that X amount of + * time has transpired before we get into the meat of the sync transaction), and + * we also set up a TQSocketNotifier, which will tell us when data is available + * to be read from the Palm socket. If we were unable to create a socket + * and/or bind to the Palm in this method, we'll start our timer again. + */ +void DeviceCommThread::openDevice() +{ + FUNCTIONSETUPL(2); + + bool deviceOpened = false; + + // This transition (from Waiting to Found) can only be + // taken once. + // + if (link()->fLinkStatus == WaitingForDevice) + { + link()->fLinkStatus = FoundDevice; + } + + if (link()->fMessages->shouldPrint(Messages::OpenMessage)) + { + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogMessage, + i18n("Trying to open device %1...") + .arg(link()->fPilotPath))); + } + + // if we're not supposed to be done, try to open the main pilot + // path... + if (!fDone && link()->fPilotPath.length() > 0) + { + DEBUGKPILOT << fname << ": Opening main pilot path: [" + << link()->fPilotPath << "]." << endl; + deviceOpened = open(link()->fPilotPath); + } + + // only try the temp device if our earlier attempt didn't work and the temp + // device is different than the main device, and it's a non-empty + // string + bool tryTemp = !deviceOpened && (link()->fTempDevice.length() > 0) && (link()->fPilotPath != link()->fTempDevice); + + // if we're not supposed to be done, and we should try the temp + // device, try the temp device... + if (!fDone && tryTemp) + { + DEBUGKPILOT << fname << ": Couldn't open main pilot path. " + << "Now trying temp device: [" + << link()->fTempDevice << "]." << endl; + deviceOpened = open(link()->fTempDevice); + } + + // if we couldn't connect, try to connect again... + if (!fDone && !deviceOpened) + { + startOpenTimer(this, fOpenTimer); + } +} + +bool DeviceCommThread::open(const TQString &device) +{ + FUNCTIONSETUPL(2); + + int ret; + int e = 0; + TQString msg; + + if (fTempSocket != -1) + { + pi_close(fTempSocket); + } + fTempSocket = (-1); + + link()->fRealPilotPath + = TDEStandardDirs::realFilePath(device.isEmpty() ? link()->fPilotPath : device); + + if ( !DeviceMap::self()->canBind(link()->fRealPilotPath) ) + { + msg = i18n("Already listening on that device"); + + WARNINGKPILOT << "Pilot Path: [" + << link()->fRealPilotPath << "] already connected." << endl; + WARNINGKPILOT << msg << endl; + + link()->fLinkStatus = PilotLinkError; + + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, msg)); + + return false; + } + + DEBUGKPILOT << fname << ": Trying to create socket." << endl; + + fTempSocket = pi_socket(PI_AF_PILOT, PI_SOCK_STREAM, PI_PF_DLP); + + if (fTempSocket < 0) + { + e = errno; + msg = i18n("Cannot create socket for communicating " + "with the Pilot (%1)").arg(errorMessage(e)); + DEBUGKPILOT << msg << endl; + DEBUGKPILOT << "(" << strerror(e) << ")" << endl; + + link()->fLinkStatus = PilotLinkError; + + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, msg)); + + return false; + } + + DEBUGKPILOT << fname << ": Got socket: [" << fTempSocket << "]" << endl; + + link()->fLinkStatus = CreatedSocket; + + DEBUGKPILOT << fname << ": Binding to path: [" + << link()->fRealPilotPath << "]" << endl; + + ret = pi_bind(fTempSocket, TQFile::encodeName(link()->fRealPilotPath)); + + if (ret < 0) + { + DEBUGKPILOT << fname + << ": pi_bind error: [" + << strerror(errno) << "]" << endl; + + e = errno; + msg = i18n("Cannot open Pilot port \"%1\". ").arg(link()->fRealPilotPath); + + DEBUGKPILOT << msg << endl; + DEBUGKPILOT << "(" << strerror(e) << ")" << endl; + + link()->fLinkStatus = PilotLinkError; + + if (link()->fMessages->shouldPrint(Messages::OpenFailMessage)) + { + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, msg)); + } + + return false; + } + + link()->fLinkStatus = DeviceOpen; + DeviceMap::self()->bindDevice(link()->fRealPilotPath); + + fSocketNotifier = new TQSocketNotifier(fTempSocket, + TQSocketNotifier::Read, this); + TQObject::connect(fSocketNotifier, TQT_SIGNAL(activated(int)), + this, TQT_SLOT(acceptDevice())); + fSocketNotifierActive=true; + + /** + * We _always_ want to set a maximum amount of time that we will wait + * for the sync process to start. In the case where our user + * has told us that he has a funky USB device, set the workaround timeout + * for shorter than normal. + */ + int timeout=20000; + if (link()->fWorkaroundUSB) + { + timeout=5000; + } + + fWorkaroundUSBTimer = new TQTimer(this); + connect(fWorkaroundUSBTimer, TQT_SIGNAL(timeout()), this, TQT_SLOT(workaroundUSB())); + fWorkaroundUSBTimer->start(timeout, true); + + return true; +} + +/** + * We've been notified by our TQSocketNotifier that we have data available on the + * socket. Try to go through the remaining steps of the connnection process. + * Note: If we return at all from this before the very end without a successful + * connection, we need to make sure we restart our connection open timer, otherwise + * it won't be restarted. + */ +void DeviceCommThread::acceptDevice() +{ + FUNCTIONSETUP; + + int ret; + + /** + * Our socket notifier should be the only reason that we end up here. + * If we're here without him being active, we have a problem. Try to clean + * up and get out. + */ + if (!fSocketNotifierActive) + { + if (!fAcceptedCount) + { + kdWarning() << k_funcinfo << ": Accidentally in acceptDevice()" + << endl; + } + fAcceptedCount++; + if (fAcceptedCount>10) + { + // Damn the torpedoes + KPILOT_DELETE(fSocketNotifier); + } + return; + } + + if (fSocketNotifier) + { + // fSocketNotifier->setEnabled(false); + fSocketNotifierActive=false; + KPILOT_DELETE(fSocketNotifier); + } + + DEBUGKPILOT << fname << ": Found connection on device: [" + << link()->pilotPath().latin1() << "]." <statusString() + << "] and socket: [" << fTempSocket << "]" << endl; + + ret = pi_listen(fTempSocket, 1); + if (ret < 0) + { + char *s = strerror(errno); + + WARNINGKPILOT << "pi_listen returned: [" << s << "]" << endl; + + // Presumably, strerror() returns things in + // local8Bit and not latin1. + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, + i18n("Cannot listen on Pilot socket (%1)"). + arg(TQString::fromLocal8Bit(s)))); + reset(); + return; + } + + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, TQString(), 10)); + + DEBUGKPILOT << fname << + ": Listening to pilot. Now trying accept..." << endl; + + int timeout = 20; + fPilotSocket = pi_accept_to(fTempSocket, 0, 0, timeout); + + if (fPilotSocket < 0) + { + char *s = strerror(errno); + + WARNINGKPILOT << "pi_accept returned: [" << s << "]" << endl; + + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, i18n("Cannot accept Pilot (%1)") + .arg(TQString::fromLocal8Bit(s)))); + + link()->fLinkStatus = PilotLinkError; + reset(); + return; + } + + DEBUGKPILOT << fname << ": Link accept done." << endl; + + if ((link()->fLinkStatus != DeviceOpen) || (fPilotSocket == -1)) + { + link()->fLinkStatus = PilotLinkError; + WARNINGKPILOT << "Already connected or unable to connect!" << endl; + + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, i18n("Cannot accept Pilot (%1)") + .arg(i18n("already connected")))); + + reset(); + return; + } + + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, TQString(), 30)); + + DEBUGKPILOT << fname << ": doing dlp_ReadSysInfo..." << endl; + + struct SysInfo sys_info; + if (dlp_ReadSysInfo(fPilotSocket, &sys_info) < 0) + { + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, + i18n("Unable to read system information from Pilot"))); + + link()->fLinkStatus=PilotLinkError; + reset(); + return; + } + else + { + DEBUGKPILOT << fname << ": dlp_ReadSysInfo successful..." << endl; + + KPILOT_DELETE(link()->fPilotSysInfo); + link()->fPilotSysInfo = new KPilotSysInfo(&sys_info); + DEBUGKPILOT << fname + << ": RomVersion: [" << link()->fPilotSysInfo->getRomVersion() + << "] Locale: [" << link()->fPilotSysInfo->getLocale() + << "] Product: [" << link()->fPilotSysInfo->getProductID() + << "]" << endl; + } + + // If we've made it this far, make sure our USB workaround timer doesn't fire! + fWorkaroundUSBTimer->stop(); + KPILOT_DELETE(fWorkaroundUSBTimer); + + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, TQString(), 60)); + + KPILOT_DELETE(link()->fPilotUser); + link()->fPilotUser = new KPilotUser; + + DEBUGKPILOT << fname << ": doing dlp_ReadUserInfo..." << endl; + + /* Ask the pilot who it is. And see if it's who we think it is. */ + dlp_ReadUserInfo(fPilotSocket, link()->fPilotUser->data()); + + TQString n = link()->getPilotUser().name(); + DEBUGKPILOT << fname + << ": Read user name: [" << n << "]" << endl; + + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, i18n("Checking last PC..."), 90)); + + /* Tell user (via Pilot) that we are starting things up */ + if ((ret=dlp_OpenConduit(fPilotSocket)) < 0) + { + DEBUGKPILOT << fname + << ": dlp_OpenConduit returned: [" << ret << "]" << endl; + + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogError, + i18n("Could not read user information from the Pilot. " + "Perhaps you have a password set on the device?"))); + + } + link()->fLinkStatus = AcceptedDevice; + + TQApplication::postEvent(link(), new DeviceCommEvent(EventLogProgress, TQString(), 100)); + + DeviceCommEvent * ev = new DeviceCommEvent(EventDeviceReady); + ev->setCurrentSocket(fPilotSocket); + TQApplication::postEvent(link(), ev); + +} + +void DeviceCommThread::workaroundUSB() +{ + FUNCTIONSETUP; + + reset(); +} + +void DeviceCommThread::run() +{ + FUNCTIONSETUP; + fDone = false; + + startOpenTimer(this, fOpenTimer); + + int sleepBetweenPoll = 2; + // keep the thread alive until we're supposed to be done + while (!fDone) + { + TQThread::sleep(sleepBetweenPoll); + } + + close(); + // now sleep one last bit to make sure the pthread inside + // pilot-link (potentially, if it's libusb) is done before we exit + TQThread::sleep(1); + + DEBUGKPILOT << fname << ": comm thread now done..." << endl; +} + +KPilotDeviceLink::KPilotDeviceLink(TQObject * parent, const char *name, + const TQString &tempDevice) : + KPilotLink(parent, name), fLinkStatus(Init), fWorkaroundUSB(false), + fPilotSocket(-1), fTempDevice(tempDevice), fMessages(new Messages(this)), fDeviceCommThread(0L) +{ + FUNCTIONSETUP; + + DEBUGKPILOT << fname + << ": Pilot-link version: [" << PILOT_LINK_NUMBER + << "]" << endl; +} + +KPilotDeviceLink::~KPilotDeviceLink() +{ + FUNCTIONSETUP; + close(); + KPILOT_DELETE(fPilotSysInfo); + KPILOT_DELETE(fPilotUser); + KPILOT_DELETE(fMessages); +} + +/* virtual */bool KPilotDeviceLink::isConnected() const +{ + return fLinkStatus == AcceptedDevice; +} + +/* virtual */bool KPilotDeviceLink::event(TQEvent *e) +{ + FUNCTIONSETUP; + + bool handled = false; + + if ((int)e->type() == EventDeviceReady) + { + DeviceCommEvent* t = static_cast(e); + fPilotSocket = t->currentSocket(); + emit deviceReady( this); + handled = true; + } + else if ((int)e->type() == EventLogMessage) + { + DeviceCommEvent* t = static_cast(e); + emit logMessage(t->message()); + handled = true; + } + else if ((int)e->type() == EventLogError) + { + DeviceCommEvent* t = static_cast(e); + emit logError(t->message()); + handled = true; + } + else if ((int)e->type() == EventLogProgress) + { + DeviceCommEvent* t = static_cast(e); + emit logProgress(t->message(), t->progress()); + handled = true; + } + else + { + handled = KPilotLink::event(e); + } + + return handled; +} + +void KPilotDeviceLink::stopCommThread() +{ + FUNCTIONSETUP; + if (fDeviceCommThread) + { + fDeviceCommThread->setDone(true); + + // try to wait for our thread to finish, but don't + // block the main thread forever + if (fDeviceCommThread->running()) + { + DEBUGKPILOT << fname + << ": comm thread still running. " + << "waiting for it to complete." << endl; + bool done = fDeviceCommThread->wait(5000); + if (!done) + { + DEBUGKPILOT << fname + << ": comm thread still running " + << "after wait(). " + << "going to have to terminate it." + << endl; + // not normally to be done, but we must make sure + // that this device doesn't come back alive + fDeviceCommThread->terminate(); + fDeviceCommThread->wait(); + } + } + + fDeviceCommThread->close(); + + KPILOT_DELETE(fDeviceCommThread); + } +} + +void KPilotDeviceLink::close() +{ + FUNCTIONSETUP; + + stopCommThread(); + + fPilotSocket = (-1); +} + +void KPilotDeviceLink::reset(const TQString & dP) +{ + FUNCTIONSETUP; + + fLinkStatus = Init; + + // Release all resources + // + close(); + fPilotPath = TQString(); + + fPilotPath = dP; + if (fPilotPath.isEmpty()) + fPilotPath = fTempDevice; + if (fPilotPath.isEmpty()) + return; + + reset(); +} + +void KPilotDeviceLink::startCommThread() +{ + FUNCTIONSETUP; + + stopCommThread(); + + if (fTempDevice.isEmpty() && pilotPath().isEmpty()) + { + WARNINGKPILOT << "No point in trying empty device." + << endl; + + TQString msg = i18n("The Pilot device is not configured yet."); + WARNINGKPILOT << msg << endl; + + fLinkStatus = PilotLinkError; + + emit logError(msg); + return; + } + + fDeviceCommThread = new DeviceCommThread(this); + fDeviceCommThread->start(); +} + +void KPilotDeviceLink::reset() +{ + FUNCTIONSETUP; + + fMessages->reset(); + close(); + + checkDevice(); + + fLinkStatus = WaitingForDevice; + + startCommThread(); +} + +void KPilotDeviceLink::checkDevice() +{ + // If the device exists yet doesn't have the right + // permissions, complain and then continue anyway. + // + TQFileInfo fi(fPilotPath); + if (fi.exists()) + { + // If it exists, it ought to be RW already. + // + if (!(fi.isReadable() && fi.isWritable())) + { + emit logError(i18n("Pilot device %1 is not read-write.") + .arg(fPilotPath)); + } + } + else + { + // It doesn't exist, mention this in the log + // (relevant as long as we use only one device type) + // + emit + logError(i18n("Pilot device %1 does not exist. " + "Probably it is a USB device and will appear during a HotSync.") + .arg(fPilotPath)); + // Suppress all normal and error messages about opening the device. + fMessages->block(Messages::OpenMessage | Messages::OpenFailMessage, + true); + } +} + +void KPilotDeviceLink::setTempDevice(const TQString &d) +{ + fTempDevice = d; + DeviceMap::self()->bindDevice(fTempDevice); +} + +/* virtual */bool KPilotDeviceLink::tickle() +{ + // No FUNCTIONSETUP here because it may be called from + // a separate thread. + return pi_tickle(pilotSocket()) >= 0; +} + +/* virtual */void KPilotDeviceLink::addSyncLogEntryImpl(const TQString &entry) +{ + dlp_AddSyncLogEntry(fPilotSocket, + const_cast((const char *)Pilot::toPilot(entry))); +} + +bool KPilotDeviceLink::installFile(const TQString & f, const bool deleteFile) +{ + FUNCTIONSETUP; + + DEBUGKPILOT << fname << ": Installing file " << f << endl; + + if (!TQFile::exists(f)) + return false; + + char buffer[PATH_MAX]; + memset(buffer, 0, PATH_MAX); + strlcpy(buffer, TQFile::encodeName(f), PATH_MAX); + struct pi_file *pf = pi_file_open(buffer); + + if (!f) + { + WARNINGKPILOT << "Cannot open file " << f << endl; + emit logError(i18n + ("Cannot install the file "%1"."). + arg(f)); + return false; + } + + if (pi_file_install(pf, fPilotSocket, 0, 0L) < 0) + { + WARNINGKPILOT << "Cannot pi_file_install " << f << endl; + emit logError(i18n + ("Cannot install the file "%1"."). + arg(f)); + return false; + } + + pi_file_close(pf); + if (deleteFile) + TQFile::remove(f); + + return true; +} + +int KPilotDeviceLink::openConduit() +{ + return dlp_OpenConduit(fPilotSocket); +} + +TQString KPilotDeviceLink::statusString(LinkStatus l) +{ + TQString s= CSL1("KPilotDeviceLink="); + + switch (l) + { + case Init: + s.append(CSL1("Init")); + break; + case WaitingForDevice: + s.append(CSL1("WaitingForDevice")); + break; + case FoundDevice: + s.append(CSL1("FoundDevice")); + break; + case CreatedSocket: + s.append(CSL1("CreatedSocket")); + break; + case DeviceOpen: + s.append(CSL1("DeviceOpen")); + break; + case AcceptedDevice: + s.append(CSL1("AcceptedDevice")); + break; + case SyncDone: + s.append(CSL1("SyncDone")); + break; + case PilotLinkError: + s.append(CSL1("PilotLinkError")); + break; + case WorkaroundUSB: + s.append(CSL1("WorkaroundUSB")); + break; + } + + return s; +} + +TQString KPilotDeviceLink::statusString() const +{ + return statusString(status() ); +} + +void KPilotDeviceLink::endSync(EndOfSyncFlags f) +{ + FUNCTIONSETUP; + + if (UpdateUserInfo == f) + { + getPilotUser().setLastSyncPC((unsigned long) gethostid()); + getPilotUser().setLastSyncDate(time(0)); + + DEBUGKPILOT << fname << ": Writing username " << getPilotUser().name() << endl; + + dlp_WriteUserInfo(pilotSocket(), getPilotUser().data()); + addSyncLogEntry(i18n("End of HotSync\n")); + } + dlp_EndOfSync(pilotSocket(), 0); + KPILOT_DELETE(fPilotSysInfo); + KPILOT_DELETE(fPilotUser); +} + +int KPilotDeviceLink::getNextDatabase(int index, struct DBInfo *dbinfo) +{ + FUNCTIONSETUP; + + pi_buffer_t buf = { 0, 0, 0 }; + int r = dlp_ReadDBList(pilotSocket(), 0, dlpDBListRAM, index, &buf); + if (r >= 0) + { + memcpy(dbinfo, buf.data, sizeof(struct DBInfo)); + } + return r; +} + +// Find a database with the given name. Info about the DB is stored into dbinfo (e.g. to be used later on with retrieveDatabase). +int KPilotDeviceLink::findDatabase(const char *name, struct DBInfo *dbinfo, + int index, unsigned long type, unsigned long creator) +{ + FUNCTIONSETUP; + return dlp_FindDBInfo(pilotSocket(), 0, index, const_cast(name), + type, creator, dbinfo); +} + +bool KPilotDeviceLink::retrieveDatabase(const TQString &fullBackupName, + DBInfo *info) +{ + FUNCTIONSETUP; + + if (fullBackupName.isEmpty() || !info) + { + // Don't even bother trying to convert or retrieve. + return false; + } + + DEBUGKPILOT << fname << ": Writing DB <" << info->name << "> " + << " to " << fullBackupName << endl; + + TQCString encodedName = TQFile::encodeName(fullBackupName); + struct pi_file *f = pi_file_create(encodedName, info); + + if (!f) + { + WARNINGKPILOT << "Failed, unable to create file" << endl; + return false; + } + + if (pi_file_retrieve(f, pilotSocket(), 0, 0L) < 0) + { + WARNINGKPILOT << "Failed, unable to back up database" << endl; + + pi_file_close(f); + return false; + } + + pi_file_close(f); + return true; +} + +KPilotLink::DBInfoList KPilotDeviceLink::getDBList(int cardno, int flags) +{ + bool cont=true; + DBInfoList dbs; + int index=0; + while (cont) + { + pi_buffer_t buf = { 0, 0, 0 }; + pi_buffer_clear(&buf); + // DBInfo*dbi=new DBInfo(); + if (dlp_ReadDBList(pilotSocket(), cardno, flags | dlpDBListMultiple, + index, &buf)<0) + { + cont=false; + } + else + { + DBInfo db_n; + DBInfo *db_it = (DBInfo *)buf.data; + int info_count = buf.used / sizeof(struct DBInfo); + + while (info_count>0) + { + memcpy(&db_n, db_it, sizeof(struct DBInfo)); + ++db_it; + info_count--; + dbs.append(db_n); + } + index=db_n.index+1; + } + } + return dbs; +} + +const KPilotCard *KPilotDeviceLink::getCardInfo(int card) +{ + KPilotCard *cardinfo=new KPilotCard(); + if (dlp_ReadStorageInfo(pilotSocket(), card, cardinfo->cardInfo())<0) + { + WARNINGKPILOT << "Could not get info for card " << card << endl; + + KPILOT_DELETE(cardinfo); + return 0L; + } + return cardinfo; +} + +PilotDatabase *KPilotDeviceLink::database(const TQString &name) +{ + return new PilotSerialDatabase( this, name ); +} + +PilotDatabase *KPilotDeviceLink::database(const DBInfo *info) +{ + return new PilotSerialDatabase( this, info ); +} + diff --git a/lib/kpilotlink.cc b/lib/kpilotlink.cc deleted file mode 100644 index b543fe7..0000000 --- a/lib/kpilotlink.cc +++ /dev/null @@ -1,272 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** Copyright (C) 2006-2007 Adriaan de Groot -** Copyright (C) 2007 Jason 'vanRijn' Kasper -** -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "pilotUser.h" -#include "pilotSysInfo.h" -#include "pilotCard.h" -#include "pilotSerialDatabase.h" -#include "pilotLocalDatabase.h" - -#include "kpilotlink.moc" - -/** Class that handles periodically tickling the handheld through -* the virtual tickle() method; deals with cancels through the -* shared fDone variable. -*/ -class TickleThread : public TQThread -{ -public: - TickleThread(KPilotLink *d, bool *done, int timeout) : - TQThread(), - fHandle(d), - fDone(done), - fTimeout(timeout) - { }; - virtual ~TickleThread(); - - virtual void run(); - - static const int ChecksPerSecond = 5; - static const int SecondsPerTickle = 5; - -private: - KPilotLink *fHandle; - bool *fDone; - int fTimeout; -} ; - -TickleThread::~TickleThread() -{ -} - -void TickleThread::run() -{ - FUNCTIONSETUP; - int subseconds = ChecksPerSecond; - int ticktock = SecondsPerTickle; - int timeout = fTimeout; - DEBUGKPILOT << fname << ": Running for " - << timeout << " seconds." << endl; - DEBUGKPILOT << fname << ": Done @" << (void *) fDone << endl; - - while (!(*fDone)) - { - TQThread::msleep(1000/ChecksPerSecond); - if (!(--subseconds)) - { - if (timeout) - { - if (!(--timeout)) - { - TQApplication::postEvent(fHandle, new TQEvent(static_cast(KPilotLink::EventTickleTimeout))); - break; - } - } - subseconds=ChecksPerSecond; - if (!(--ticktock)) - { - ticktock=SecondsPerTickle; - fHandle->tickle(); - } - } - } -} - - - - - - - - - -KPilotLink::KPilotLink( TQObject *parent, const char *name ) : - TQObject( parent, name ), - fPilotPath(TQString()), - fPilotUser(0L), - fPilotSysInfo(0L), - fTickleDone(true), - fTickleThread(0L) - -{ - FUNCTIONSETUP; - - fPilotUser = new KPilotUser(); - strncpy( fPilotUser->data()->username, "Henk Westbroek", - sizeof(fPilotUser->data()->username)-1); - fPilotUser->setLastSuccessfulSyncDate( 1139171019 ); - - fPilotSysInfo = new KPilotSysInfo(); - memset(fPilotSysInfo->sysInfo()->prodID, 0, - sizeof(fPilotSysInfo->sysInfo()->prodID)); - strncpy(fPilotSysInfo->sysInfo()->prodID, "LocalLink", - sizeof(fPilotSysInfo->sysInfo()->prodID)-1); - fPilotSysInfo->sysInfo()->prodIDLength = - strlen(fPilotSysInfo->sysInfo()->prodID); -} - -KPilotLink::~KPilotLink() -{ - FUNCTIONSETUP; - KPILOT_DELETE(fPilotUser); - KPILOT_DELETE(fPilotSysInfo); -} - -/* virtual */ bool KPilotLink::event(TQEvent *e) -{ - if ((int)e->type() == EventTickleTimeout) - { - stopTickle(); - emit timeout(); - return true; - } - else return TQObject::event(e); -} - -/* -Start a tickle thread with the indicated timeout. -*/ -void KPilotLink::startTickle(unsigned int timeout) -{ - FUNCTIONSETUP; - - Q_ASSERT(fTickleDone); - - /* - ** We've told the thread to finish up, but it hasn't - ** done so yet - so wait for it to do so, should be - ** only 200ms at most. - */ - if (fTickleDone && fTickleThread) - { - fTickleThread->wait(); - KPILOT_DELETE(fTickleThread); - } - - DEBUGKPILOT << fname << ": Done @" << (void *) (&fTickleDone) << endl; - - fTickleDone = false; - fTickleThread = new TickleThread(this,&fTickleDone,timeout); - fTickleThread->start(); -} - -void KPilotLink::stopTickle() -{ - FUNCTIONSETUP; - fTickleDone = true; - if (fTickleThread) - { - fTickleThread->wait(); - KPILOT_DELETE(fTickleThread); - } -} - -unsigned int KPilotLink::installFiles(const TQStringList & l, const bool deleteFiles) -{ - FUNCTIONSETUP; - - TQStringList::ConstIterator i,e; - unsigned int k = 0; - unsigned int n = 0; - unsigned int total = l.count(); - - for (i = l.begin(), e = l.end(); i != e; ++i) - { - emit logProgress(TQString(), - (int) ((100.0 / total) * (float) n)); - - if (installFile(*i, deleteFiles)) - k++; - n++; - } - emit logProgress(TQString(), 100); - - return k; -} - -void KPilotLink::addSyncLogEntry(const TQString & entry, bool log) -{ - FUNCTIONSETUP; - if (entry.isEmpty()) return; - - addSyncLogEntryImpl(entry); - if (log) - { - emit logMessage(entry); - } -} - - -/* virtual */ int KPilotLink::openConduit() -{ - return 0; -} - -/* virtual */ int KPilotLink::pilotSocket() const -{ - return -1; -} - -/* virtual */ PilotDatabase *KPilotLink::database( const DBInfo *info ) -{ - FUNCTIONSETUP; - return database( Pilot::fromPilot( info->name ) ); -} - diff --git a/lib/kpilotlink.cpp b/lib/kpilotlink.cpp new file mode 100644 index 0000000..b543fe7 --- /dev/null +++ b/lib/kpilotlink.cpp @@ -0,0 +1,272 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** Copyright (C) 2006-2007 Adriaan de Groot +** Copyright (C) 2007 Jason 'vanRijn' Kasper +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pilotUser.h" +#include "pilotSysInfo.h" +#include "pilotCard.h" +#include "pilotSerialDatabase.h" +#include "pilotLocalDatabase.h" + +#include "kpilotlink.moc" + +/** Class that handles periodically tickling the handheld through +* the virtual tickle() method; deals with cancels through the +* shared fDone variable. +*/ +class TickleThread : public TQThread +{ +public: + TickleThread(KPilotLink *d, bool *done, int timeout) : + TQThread(), + fHandle(d), + fDone(done), + fTimeout(timeout) + { }; + virtual ~TickleThread(); + + virtual void run(); + + static const int ChecksPerSecond = 5; + static const int SecondsPerTickle = 5; + +private: + KPilotLink *fHandle; + bool *fDone; + int fTimeout; +} ; + +TickleThread::~TickleThread() +{ +} + +void TickleThread::run() +{ + FUNCTIONSETUP; + int subseconds = ChecksPerSecond; + int ticktock = SecondsPerTickle; + int timeout = fTimeout; + DEBUGKPILOT << fname << ": Running for " + << timeout << " seconds." << endl; + DEBUGKPILOT << fname << ": Done @" << (void *) fDone << endl; + + while (!(*fDone)) + { + TQThread::msleep(1000/ChecksPerSecond); + if (!(--subseconds)) + { + if (timeout) + { + if (!(--timeout)) + { + TQApplication::postEvent(fHandle, new TQEvent(static_cast(KPilotLink::EventTickleTimeout))); + break; + } + } + subseconds=ChecksPerSecond; + if (!(--ticktock)) + { + ticktock=SecondsPerTickle; + fHandle->tickle(); + } + } + } +} + + + + + + + + + +KPilotLink::KPilotLink( TQObject *parent, const char *name ) : + TQObject( parent, name ), + fPilotPath(TQString()), + fPilotUser(0L), + fPilotSysInfo(0L), + fTickleDone(true), + fTickleThread(0L) + +{ + FUNCTIONSETUP; + + fPilotUser = new KPilotUser(); + strncpy( fPilotUser->data()->username, "Henk Westbroek", + sizeof(fPilotUser->data()->username)-1); + fPilotUser->setLastSuccessfulSyncDate( 1139171019 ); + + fPilotSysInfo = new KPilotSysInfo(); + memset(fPilotSysInfo->sysInfo()->prodID, 0, + sizeof(fPilotSysInfo->sysInfo()->prodID)); + strncpy(fPilotSysInfo->sysInfo()->prodID, "LocalLink", + sizeof(fPilotSysInfo->sysInfo()->prodID)-1); + fPilotSysInfo->sysInfo()->prodIDLength = + strlen(fPilotSysInfo->sysInfo()->prodID); +} + +KPilotLink::~KPilotLink() +{ + FUNCTIONSETUP; + KPILOT_DELETE(fPilotUser); + KPILOT_DELETE(fPilotSysInfo); +} + +/* virtual */ bool KPilotLink::event(TQEvent *e) +{ + if ((int)e->type() == EventTickleTimeout) + { + stopTickle(); + emit timeout(); + return true; + } + else return TQObject::event(e); +} + +/* +Start a tickle thread with the indicated timeout. +*/ +void KPilotLink::startTickle(unsigned int timeout) +{ + FUNCTIONSETUP; + + Q_ASSERT(fTickleDone); + + /* + ** We've told the thread to finish up, but it hasn't + ** done so yet - so wait for it to do so, should be + ** only 200ms at most. + */ + if (fTickleDone && fTickleThread) + { + fTickleThread->wait(); + KPILOT_DELETE(fTickleThread); + } + + DEBUGKPILOT << fname << ": Done @" << (void *) (&fTickleDone) << endl; + + fTickleDone = false; + fTickleThread = new TickleThread(this,&fTickleDone,timeout); + fTickleThread->start(); +} + +void KPilotLink::stopTickle() +{ + FUNCTIONSETUP; + fTickleDone = true; + if (fTickleThread) + { + fTickleThread->wait(); + KPILOT_DELETE(fTickleThread); + } +} + +unsigned int KPilotLink::installFiles(const TQStringList & l, const bool deleteFiles) +{ + FUNCTIONSETUP; + + TQStringList::ConstIterator i,e; + unsigned int k = 0; + unsigned int n = 0; + unsigned int total = l.count(); + + for (i = l.begin(), e = l.end(); i != e; ++i) + { + emit logProgress(TQString(), + (int) ((100.0 / total) * (float) n)); + + if (installFile(*i, deleteFiles)) + k++; + n++; + } + emit logProgress(TQString(), 100); + + return k; +} + +void KPilotLink::addSyncLogEntry(const TQString & entry, bool log) +{ + FUNCTIONSETUP; + if (entry.isEmpty()) return; + + addSyncLogEntryImpl(entry); + if (log) + { + emit logMessage(entry); + } +} + + +/* virtual */ int KPilotLink::openConduit() +{ + return 0; +} + +/* virtual */ int KPilotLink::pilotSocket() const +{ + return -1; +} + +/* virtual */ PilotDatabase *KPilotLink::database( const DBInfo *info ) +{ + FUNCTIONSETUP; + return database( Pilot::fromPilot( info->name ) ); +} + diff --git a/lib/kpilotlocallink.cc b/lib/kpilotlocallink.cc deleted file mode 100644 index b5ec450..0000000 --- a/lib/kpilotlocallink.cc +++ /dev/null @@ -1,368 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** Copyright (C) 2006-2007 Adriaan de Groot -** Copyright (C) 2007 Jason 'vanRijn' Kasper -** -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "pilotSerialDatabase.h" -#include "pilotLocalDatabase.h" - -#include "kpilotlink.h" -#include "kpilotlocallink.moc" - - -typedef TQPair DatabaseDescriptor; -typedef TQValueList DatabaseDescriptorList; - -class KPilotLocalLink::Private -{ -public: - DatabaseDescriptorList fDBs; -} ; - -unsigned int KPilotLocalLink::findAvailableDatabases( KPilotLocalLink::Private &info, const TQString &path ) -{ - FUNCTIONSETUP; - - info.fDBs.clear(); - - TQDir d(path); - if (!d.exists()) - { - // Perhaps return an error? - return 0; - } - - // Use this to fake indexes in the list of DBInfo structs - unsigned int counter = 0; - - TQStringList dbs = d.entryList( CSL1("*.pdb"), TQDir::Files | TQDir::NoSymLinks | TQDir::Readable ); - for ( TQStringList::ConstIterator i = dbs.begin(); i != dbs.end() ; ++i) - { - struct DBInfo dbi; - - // Remove the trailing 4 characters - TQString dbname = (*i); - dbname.remove(dbname.length()-4,4); - - TQString dbnamecheck = (*i).left((*i).findRev(CSL1(".pdb"))); - Q_ASSERT(dbname == dbnamecheck); - - if (PilotLocalDatabase::infoFromFile( path + CSL1("/") + (*i), &dbi)) - { - DEBUGKPILOT << fname << ": Loaded " - << dbname << endl; - dbi.index = counter; - info.fDBs.append( DatabaseDescriptor(dbname,dbi) ); - ++counter; - } - } - - DEBUGKPILOT << fname << ": Total " << info.fDBs.count() - << " databases." << endl; - return info.fDBs.count(); -} - - -KPilotLocalLink::KPilotLocalLink( TQObject *parent, const char *name ) : - KPilotLink(parent,name), - fReady(false), - d( new Private ) -{ - FUNCTIONSETUP; -} - -KPilotLocalLink::~KPilotLocalLink() -{ - FUNCTIONSETUP; - KPILOT_DELETE(d); -} - -/* virtual */ TQString KPilotLocalLink::statusString() const -{ - return fReady ? CSL1("Ready") : CSL1("Waiting") ; -} - -/* virtual */ bool KPilotLocalLink::isConnected() const -{ - return fReady; -} - -/* virtual */ void KPilotLocalLink::reset( const TQString &p ) -{ - FUNCTIONSETUP; - fPath = p; - reset(); -} - -/* virtual */ void KPilotLocalLink::reset() -{ - FUNCTIONSETUP; - TQFileInfo info( fPath ); - fReady = !fPath.isEmpty() && info.exists() && info.isDir() ; - if (fReady) - { - findAvailableDatabases(*d, fPath); - TQTimer::singleShot(500,this,TQT_SLOT(ready())); - } - else - { - WARNINGKPILOT << "The local link path <" - << fPath - << "> does not exist or is not a directory. No sync can be done." - << endl; - } -} - -/* virtual */ void KPilotLocalLink::close() -{ - fReady = false; -} - -/* virtual */ bool KPilotLocalLink::tickle() -{ - return true; -} - -/* virtual */ const KPilotCard *KPilotLocalLink::getCardInfo(int) -{ - return 0; -} - -/* virtual */ void KPilotLocalLink::endSync( EndOfSyncFlags f ) -{ - Q_UNUSED(f); - fReady = false; -} - -/* virtual */ int KPilotLocalLink::openConduit() -{ - FUNCTIONSETUP; - return 0; -} - - -/* virtual */ int KPilotLocalLink::getNextDatabase( int index, struct DBInfo *info ) -{ - FUNCTIONSETUP; - - if ( (index<0) || (index>=(int)d->fDBs.count()) ) - { - WARNINGKPILOT << "Index out of range." << endl; - return -1; - } - - DatabaseDescriptor dd = d->fDBs[index]; - - DEBUGKPILOT << fname << ": Getting database " << dd.first << endl; - - if (info) - { - *info = dd.second; - } - - return index+1; -} - -/* virtual */ int KPilotLocalLink::findDatabase(const char *name, struct DBInfo*info, - int index, unsigned long type, unsigned long creator) -{ - FUNCTIONSETUP; - - if ( (index<0) || (index>=(int)d->fDBs.count()) ) - { - WARNINGKPILOT << "Index out of range." << endl; - return -1; - } - - if (!name) - { - WARNINGKPILOT << "NULL name." << endl; - return -1; - } - - TQString desiredName = Pilot::fromPilot(name); - DEBUGKPILOT << fname << ": Looking for DB " << desiredName << endl; - for ( DatabaseDescriptorList::ConstIterator i = d->fDBs.at(index); - i != d->fDBs.end(); ++i) - { - const DatabaseDescriptor &dd = *i; - if (dd.first == desiredName) - { - if ( (!type || (type == dd.second.type)) && - (!creator || (creator == dd.second.creator)) ) - { - if (info) - { - *info = dd.second; - } - return index; - } - } - - ++index; - } - - return -1; -} - -/* virtual */ void KPilotLocalLink::addSyncLogEntryImpl(TQString const &s) -{ - FUNCTIONSETUP; - DEBUGKPILOT << fname << ": " << s << endl ; -} - -/* virtual */ bool KPilotLocalLink::installFile(TQString const &path, bool deletefile) -{ - FUNCTIONSETUP; - - TQFileInfo srcInfo(path); - TQString canonicalSrcPath = srcInfo.dir().canonicalPath() + CSL1("/") + srcInfo.fileName() ; - TQString canonicalDstPath = fPath + CSL1("/") + srcInfo.fileName(); - - if (canonicalSrcPath == canonicalDstPath) - { - // That's a cheap copy operation - return true; - } - - KURL src = KURL::fromPathOrURL( canonicalSrcPath ); - KURL dst = KURL::fromPathOrURL( canonicalDstPath ); - - TDEIO::NetAccess::file_copy(src,dst,-1,true); - - if (deletefile) - { - TDEIO::NetAccess::del(src, 0L); - } - - return true; -} - -/* virtual */ bool KPilotLocalLink::retrieveDatabase( const TQString &path, struct DBInfo *db ) -{ - FUNCTIONSETUP; - - TQString dbname = Pilot::fromPilot(db->name) + CSL1(".pdb") ; - TQString sourcefile = fPath + CSL1("/") + dbname ; - TQString destfile = path ; - - DEBUGKPILOT << fname << ": src=" << sourcefile << endl; - DEBUGKPILOT << fname << ": dst=" << destfile << endl; - - TQFile in( sourcefile ); - if ( !in.exists() ) - { - WARNINGKPILOT << "Source file " << sourcefile << " doesn't exist." << endl; - return false; - } - if ( !in.open( IO_ReadOnly | IO_Raw ) ) - { - WARNINGKPILOT << "Can't read source file " << sourcefile << endl; - return false; - } - - TQFile out( destfile ); - if ( !out.open( IO_WriteOnly | IO_Truncate | IO_Raw ) ) - { - WARNINGKPILOT << "Can't write destination file " << destfile << endl; - return false; - } - - const TQ_ULONG BUF_SIZ = 8192 ; - char buf[BUF_SIZ]; - TQ_LONG r; - - while ( (r=in.readBlock(buf,BUF_SIZ))>0 ) - { - out.writeBlock(buf,r); - } - out.flush(); - in.close(); - - return out.exists(); -} - -KPilotLink::DBInfoList KPilotLocalLink::getDBList( int, int ) -{ - FUNCTIONSETUP; - DBInfoList l; - for ( DatabaseDescriptorList::ConstIterator i=d->fDBs.begin(); - i != d->fDBs.end(); ++i) - { - l.append( (*i).second ); - } - return l; -} - - -/* virtual */ PilotDatabase *KPilotLocalLink::database( const TQString &name ) -{ - FUNCTIONSETUP; - return new PilotLocalDatabase( fPath, name ); -} - - - -/* slot */ void KPilotLocalLink::ready() -{ - if (fReady) - { - emit deviceReady(this); - } -} - diff --git a/lib/kpilotlocallink.cpp b/lib/kpilotlocallink.cpp new file mode 100644 index 0000000..b5ec450 --- /dev/null +++ b/lib/kpilotlocallink.cpp @@ -0,0 +1,368 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** Copyright (C) 2006-2007 Adriaan de Groot +** Copyright (C) 2007 Jason 'vanRijn' Kasper +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pilotSerialDatabase.h" +#include "pilotLocalDatabase.h" + +#include "kpilotlink.h" +#include "kpilotlocallink.moc" + + +typedef TQPair DatabaseDescriptor; +typedef TQValueList DatabaseDescriptorList; + +class KPilotLocalLink::Private +{ +public: + DatabaseDescriptorList fDBs; +} ; + +unsigned int KPilotLocalLink::findAvailableDatabases( KPilotLocalLink::Private &info, const TQString &path ) +{ + FUNCTIONSETUP; + + info.fDBs.clear(); + + TQDir d(path); + if (!d.exists()) + { + // Perhaps return an error? + return 0; + } + + // Use this to fake indexes in the list of DBInfo structs + unsigned int counter = 0; + + TQStringList dbs = d.entryList( CSL1("*.pdb"), TQDir::Files | TQDir::NoSymLinks | TQDir::Readable ); + for ( TQStringList::ConstIterator i = dbs.begin(); i != dbs.end() ; ++i) + { + struct DBInfo dbi; + + // Remove the trailing 4 characters + TQString dbname = (*i); + dbname.remove(dbname.length()-4,4); + + TQString dbnamecheck = (*i).left((*i).findRev(CSL1(".pdb"))); + Q_ASSERT(dbname == dbnamecheck); + + if (PilotLocalDatabase::infoFromFile( path + CSL1("/") + (*i), &dbi)) + { + DEBUGKPILOT << fname << ": Loaded " + << dbname << endl; + dbi.index = counter; + info.fDBs.append( DatabaseDescriptor(dbname,dbi) ); + ++counter; + } + } + + DEBUGKPILOT << fname << ": Total " << info.fDBs.count() + << " databases." << endl; + return info.fDBs.count(); +} + + +KPilotLocalLink::KPilotLocalLink( TQObject *parent, const char *name ) : + KPilotLink(parent,name), + fReady(false), + d( new Private ) +{ + FUNCTIONSETUP; +} + +KPilotLocalLink::~KPilotLocalLink() +{ + FUNCTIONSETUP; + KPILOT_DELETE(d); +} + +/* virtual */ TQString KPilotLocalLink::statusString() const +{ + return fReady ? CSL1("Ready") : CSL1("Waiting") ; +} + +/* virtual */ bool KPilotLocalLink::isConnected() const +{ + return fReady; +} + +/* virtual */ void KPilotLocalLink::reset( const TQString &p ) +{ + FUNCTIONSETUP; + fPath = p; + reset(); +} + +/* virtual */ void KPilotLocalLink::reset() +{ + FUNCTIONSETUP; + TQFileInfo info( fPath ); + fReady = !fPath.isEmpty() && info.exists() && info.isDir() ; + if (fReady) + { + findAvailableDatabases(*d, fPath); + TQTimer::singleShot(500,this,TQT_SLOT(ready())); + } + else + { + WARNINGKPILOT << "The local link path <" + << fPath + << "> does not exist or is not a directory. No sync can be done." + << endl; + } +} + +/* virtual */ void KPilotLocalLink::close() +{ + fReady = false; +} + +/* virtual */ bool KPilotLocalLink::tickle() +{ + return true; +} + +/* virtual */ const KPilotCard *KPilotLocalLink::getCardInfo(int) +{ + return 0; +} + +/* virtual */ void KPilotLocalLink::endSync( EndOfSyncFlags f ) +{ + Q_UNUSED(f); + fReady = false; +} + +/* virtual */ int KPilotLocalLink::openConduit() +{ + FUNCTIONSETUP; + return 0; +} + + +/* virtual */ int KPilotLocalLink::getNextDatabase( int index, struct DBInfo *info ) +{ + FUNCTIONSETUP; + + if ( (index<0) || (index>=(int)d->fDBs.count()) ) + { + WARNINGKPILOT << "Index out of range." << endl; + return -1; + } + + DatabaseDescriptor dd = d->fDBs[index]; + + DEBUGKPILOT << fname << ": Getting database " << dd.first << endl; + + if (info) + { + *info = dd.second; + } + + return index+1; +} + +/* virtual */ int KPilotLocalLink::findDatabase(const char *name, struct DBInfo*info, + int index, unsigned long type, unsigned long creator) +{ + FUNCTIONSETUP; + + if ( (index<0) || (index>=(int)d->fDBs.count()) ) + { + WARNINGKPILOT << "Index out of range." << endl; + return -1; + } + + if (!name) + { + WARNINGKPILOT << "NULL name." << endl; + return -1; + } + + TQString desiredName = Pilot::fromPilot(name); + DEBUGKPILOT << fname << ": Looking for DB " << desiredName << endl; + for ( DatabaseDescriptorList::ConstIterator i = d->fDBs.at(index); + i != d->fDBs.end(); ++i) + { + const DatabaseDescriptor &dd = *i; + if (dd.first == desiredName) + { + if ( (!type || (type == dd.second.type)) && + (!creator || (creator == dd.second.creator)) ) + { + if (info) + { + *info = dd.second; + } + return index; + } + } + + ++index; + } + + return -1; +} + +/* virtual */ void KPilotLocalLink::addSyncLogEntryImpl(TQString const &s) +{ + FUNCTIONSETUP; + DEBUGKPILOT << fname << ": " << s << endl ; +} + +/* virtual */ bool KPilotLocalLink::installFile(TQString const &path, bool deletefile) +{ + FUNCTIONSETUP; + + TQFileInfo srcInfo(path); + TQString canonicalSrcPath = srcInfo.dir().canonicalPath() + CSL1("/") + srcInfo.fileName() ; + TQString canonicalDstPath = fPath + CSL1("/") + srcInfo.fileName(); + + if (canonicalSrcPath == canonicalDstPath) + { + // That's a cheap copy operation + return true; + } + + KURL src = KURL::fromPathOrURL( canonicalSrcPath ); + KURL dst = KURL::fromPathOrURL( canonicalDstPath ); + + TDEIO::NetAccess::file_copy(src,dst,-1,true); + + if (deletefile) + { + TDEIO::NetAccess::del(src, 0L); + } + + return true; +} + +/* virtual */ bool KPilotLocalLink::retrieveDatabase( const TQString &path, struct DBInfo *db ) +{ + FUNCTIONSETUP; + + TQString dbname = Pilot::fromPilot(db->name) + CSL1(".pdb") ; + TQString sourcefile = fPath + CSL1("/") + dbname ; + TQString destfile = path ; + + DEBUGKPILOT << fname << ": src=" << sourcefile << endl; + DEBUGKPILOT << fname << ": dst=" << destfile << endl; + + TQFile in( sourcefile ); + if ( !in.exists() ) + { + WARNINGKPILOT << "Source file " << sourcefile << " doesn't exist." << endl; + return false; + } + if ( !in.open( IO_ReadOnly | IO_Raw ) ) + { + WARNINGKPILOT << "Can't read source file " << sourcefile << endl; + return false; + } + + TQFile out( destfile ); + if ( !out.open( IO_WriteOnly | IO_Truncate | IO_Raw ) ) + { + WARNINGKPILOT << "Can't write destination file " << destfile << endl; + return false; + } + + const TQ_ULONG BUF_SIZ = 8192 ; + char buf[BUF_SIZ]; + TQ_LONG r; + + while ( (r=in.readBlock(buf,BUF_SIZ))>0 ) + { + out.writeBlock(buf,r); + } + out.flush(); + in.close(); + + return out.exists(); +} + +KPilotLink::DBInfoList KPilotLocalLink::getDBList( int, int ) +{ + FUNCTIONSETUP; + DBInfoList l; + for ( DatabaseDescriptorList::ConstIterator i=d->fDBs.begin(); + i != d->fDBs.end(); ++i) + { + l.append( (*i).second ); + } + return l; +} + + +/* virtual */ PilotDatabase *KPilotLocalLink::database( const TQString &name ) +{ + FUNCTIONSETUP; + return new PilotLocalDatabase( fPath, name ); +} + + + +/* slot */ void KPilotLocalLink::ready() +{ + if (fReady) + { + emit deviceReady(this); + } +} + diff --git a/lib/kpilotlocallink.h b/lib/kpilotlocallink.h index fd74bab..eeeb298 100644 --- a/lib/kpilotlocallink.h +++ b/lib/kpilotlocallink.h @@ -32,7 +32,7 @@ #include "kpilotlink.h" /** @file -* Definition of the local link class; implemented in kpilotlink.cc . +* Definition of the local link class; implemented in kpilotlink.cpp . */ diff --git a/lib/options.cc b/lib/options.cc deleted file mode 100644 index f7ee6de..0000000 --- a/lib/options.cc +++ /dev/null @@ -1,157 +0,0 @@ -/* KPilot -** -** Copyright (C) 2000-2001 by Adriaan de Groot -** Copyright (C) 2003-2004 Reinhold Kainhofer -** -** This is a file of odds and ends, with debugging functions and stuff. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 - -#include - -#include -#include -#include - -#ifdef DEBUG -int debug_level = 1; -#else -int debug_level = 0; -#endif - -// The daemon also has a debug level; debug_spaces is 60 spaces, -// to align FUNCTIONSETUP output. The one byte extra is for the NUL. -// -// -static const char debug_spaces[61] = - " " - " " - " "; - - -TQString rtExpand(const TQString &s, TQt::TextFormat richText) -{ - if (richText == TQt::RichText) - { - TQString t(s); - return t.replace(CSL1("\n"), CSL1("
\n")); - } - else - { - return s; - } - -} - -TQDateTime readTm(const struct tm &t) -{ - TQDateTime dt; - dt.setDate(TQDate(1900 + t.tm_year, t.tm_mon + 1, t.tm_mday)); - dt.setTime(TQTime(t.tm_hour, t.tm_min, t.tm_sec)); - return dt; -} - - - -struct tm writeTm(const TQDateTime &dt) -{ - struct tm t; - - t.tm_wday = 0; // unimplemented - t.tm_yday = 0; // unimplemented - t.tm_isdst = 0; // unimplemented -#ifdef HAVE_STRUCT_TM_TM_ZONE - t.tm_zone = 0; // unimplemented -#endif - - t.tm_year = dt.date().year() - 1900; - t.tm_mon = dt.date().month() - 1; - t.tm_mday = dt.date().day(); - t.tm_hour = dt.time().hour(); - t.tm_min = dt.time().minute(); - t.tm_sec = dt.time().second(); - - return t; -} - - - -struct tm writeTm(const TQDate &d) -{ - TQDateTime dt(d); - return writeTm(dt); -} - -KPilotDepthCount::KPilotDepthCount(int, int level, const char *s) : - fDepth(depth), - fLevel(level), - fName(s) -{ - DEBUGKPILOT << "! DEPRECATED Depth call.\n! " - << kdBacktrace(4) << endl; - - if (debug_level>=fLevel) - { - DEBUGKPILOT << indent() << ">" << name() << endl; - } - depth++; -} - -KPilotDepthCount::KPilotDepthCount(int level, const char *s) : - fDepth(depth), - fLevel(level), - fName(s) -{ - if (debug_level>=fLevel) - { - DEBUGKPILOT << indent() << ">" << name() << endl; - } - depth++; -} - -KPilotDepthCount::~KPilotDepthCount() -{ - depth--; - std::cerr.clear(std::ios_base::goodbit); -} - -const char *KPilotDepthCount::indent() const -{ - if (fDepth < 30) - { - return debug_spaces + 60-fDepth*2; - } - else - { - return debug_spaces; - } -} - -int KPilotDepthCount::depth = 0; - diff --git a/lib/options.cpp b/lib/options.cpp new file mode 100644 index 0000000..f7ee6de --- /dev/null +++ b/lib/options.cpp @@ -0,0 +1,157 @@ +/* KPilot +** +** Copyright (C) 2000-2001 by Adriaan de Groot +** Copyright (C) 2003-2004 Reinhold Kainhofer +** +** This is a file of odds and ends, with debugging functions and stuff. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 + +#include + +#include +#include +#include + +#ifdef DEBUG +int debug_level = 1; +#else +int debug_level = 0; +#endif + +// The daemon also has a debug level; debug_spaces is 60 spaces, +// to align FUNCTIONSETUP output. The one byte extra is for the NUL. +// +// +static const char debug_spaces[61] = + " " + " " + " "; + + +TQString rtExpand(const TQString &s, TQt::TextFormat richText) +{ + if (richText == TQt::RichText) + { + TQString t(s); + return t.replace(CSL1("\n"), CSL1("
\n")); + } + else + { + return s; + } + +} + +TQDateTime readTm(const struct tm &t) +{ + TQDateTime dt; + dt.setDate(TQDate(1900 + t.tm_year, t.tm_mon + 1, t.tm_mday)); + dt.setTime(TQTime(t.tm_hour, t.tm_min, t.tm_sec)); + return dt; +} + + + +struct tm writeTm(const TQDateTime &dt) +{ + struct tm t; + + t.tm_wday = 0; // unimplemented + t.tm_yday = 0; // unimplemented + t.tm_isdst = 0; // unimplemented +#ifdef HAVE_STRUCT_TM_TM_ZONE + t.tm_zone = 0; // unimplemented +#endif + + t.tm_year = dt.date().year() - 1900; + t.tm_mon = dt.date().month() - 1; + t.tm_mday = dt.date().day(); + t.tm_hour = dt.time().hour(); + t.tm_min = dt.time().minute(); + t.tm_sec = dt.time().second(); + + return t; +} + + + +struct tm writeTm(const TQDate &d) +{ + TQDateTime dt(d); + return writeTm(dt); +} + +KPilotDepthCount::KPilotDepthCount(int, int level, const char *s) : + fDepth(depth), + fLevel(level), + fName(s) +{ + DEBUGKPILOT << "! DEPRECATED Depth call.\n! " + << kdBacktrace(4) << endl; + + if (debug_level>=fLevel) + { + DEBUGKPILOT << indent() << ">" << name() << endl; + } + depth++; +} + +KPilotDepthCount::KPilotDepthCount(int level, const char *s) : + fDepth(depth), + fLevel(level), + fName(s) +{ + if (debug_level>=fLevel) + { + DEBUGKPILOT << indent() << ">" << name() << endl; + } + depth++; +} + +KPilotDepthCount::~KPilotDepthCount() +{ + depth--; + std::cerr.clear(std::ios_base::goodbit); +} + +const char *KPilotDepthCount::indent() const +{ + if (fDepth < 30) + { + return debug_spaces + 60-fDepth*2; + } + else + { + return debug_spaces; + } +} + +int KPilotDepthCount::depth = 0; + diff --git a/lib/pilot.cc b/lib/pilot.cc deleted file mode 100644 index d15eb55..0000000 --- a/lib/pilot.cc +++ /dev/null @@ -1,264 +0,0 @@ -/* pilot.cc KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** Copyright (C) 2003-2006 Adriaan de Groot -** -** These are the base class structures that reside on the -** handheld device -- databases and their parts. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 -#include -#include -#include - -#include "pilot.h" -#include "pilotDatabase.h" -#include "pilotAppInfo.h" -#include "pilotRecord.h" - - -namespace Pilot -{ -static TQTextCodec *codec = 0L; -static TQMutex* mutex = 0L; - - -TQString fromPilot( const char *c, int len ) -{ - mutex->lock(); - TQString str = codec->toUnicode(c,len); - mutex->unlock(); - return str; -} - -TQString fromPilot( const char *c ) -{ - mutex->lock(); - TQString str = codec->toUnicode(c); - mutex->unlock(); - return str; -} - -TQCString toPilot( const TQString &s ) -{ - mutex->lock(); - TQCString str = codec->fromUnicode(s); - mutex->unlock(); - return str; -} - -int toPilot( const TQString &s, char *buf, int len) -{ - mutex->lock(); - // See toPilot() below. - memset( buf, 0, len ); - int used = len; - TQCString cbuf = codec->fromUnicode(s,used); - if (used > len) - { - used=len; - } - memcpy( buf, cbuf.data(), used ); - mutex->unlock(); - return used; -} - -int toPilot( const TQString &s, unsigned char *buf, int len) -{ - mutex->lock(); - // Clear the buffer - memset( buf, 0, len ); - - // Convert to 8-bit encoding - int used = len; - TQCString cbuf = codec->fromUnicode(s,used); - - // Will it fit in the buffer? - if (used > len) - { - // Ought to be impossible, anyway, since 8-bit encodings - // are shorter than the UTF-8 encodings (1 byte per character - // vs. 1-or-more byte per character). - used=len; - } - - // Fill the buffer with encoded data. - memcpy( buf, cbuf.data(), used ); - mutex->unlock(); - return used; -} - -bool setupPilotCodec(const TQString &s) -{ - FUNCTIONSETUP; - mutex = new TQMutex(); - mutex->lock(); - TQString encoding(TDEGlobal::charsets()->encodingForName(s)); - - DEBUGKPILOT << fname << ": Using codec name " << s << endl; - DEBUGKPILOT << fname << ": Creating codec " << encoding << endl; - - // if the desired codec can't be found, latin1 will be returned anyway, no need to do this manually - codec = TDEGlobal::charsets()->codecForName(encoding); - - if (codec) - { - DEBUGKPILOT << fname << ": Got codec " << codec->name() << endl; - } - - mutex->unlock(); - return codec; -} - -TQString codecName() -{ - return TQString::fromLatin1(codec->name()); -} - -TQString category(const struct CategoryAppInfo *info, unsigned int i) -{ - if (!info || (i>=CATEGORY_COUNT)) - { - return TQString(); - } - - mutex->lock(); - TQString str = codec->toUnicode(info->name[i], - MIN(strlen(info->name[i]), CATEGORY_SIZE-1)); - mutex->unlock(); - return str; -} - - -int findCategory(const struct CategoryAppInfo *info, - const TQString &selectedCategory, - bool unknownIsUnfiled) -{ - FUNCTIONSETUP; - - if (!info) - { - WARNINGKPILOT << "Bad CategoryAppInfo pointer" << endl; - return -1; - } - - int currentCatID = -1; - for (unsigned int i=0; iname[i][0]) continue; - if (selectedCategory == category(info, i)) - { - currentCatID = i; - break; - } - } - - if (-1 == currentCatID) - { - DEBUGKPILOT << fname << ": Category name " - << selectedCategory << " not found." << endl; - } - else - { - DEBUGKPILOT << fname << ": Matched category " << currentCatID << endl; - } - - if ((currentCatID == -1) && unknownIsUnfiled) - currentCatID = 0; - return currentCatID; -} - -int insertCategory(struct CategoryAppInfo *info, - const TQString &label, - bool unknownIsUnfiled) -{ - FUNCTIONSETUP; - - if (!info) - { - WARNINGKPILOT << "Bad CategoryAppInfo pointer" << endl; - return -1; - } - - - int c = findCategory(info,label,unknownIsUnfiled); - if (c<0) - { - // This is the case when the category is not known - // and unknownIsUnfiled is false. - for (unsigned int i=0; iname[i][0]) - { - c = i; - break; - } - } - - if ((c>0) && (c < (int)CATEGORY_COUNT)) - { - // 0 is always unfiled, can't change that. - toPilot(label,info->name[c],CATEGORY_SIZE); - } - else - { - WARNINGKPILOT << "Category name " - << label - << " could not be added." << endl; - c = -1; - } - } - - return c; -} - -void dumpCategories(const struct CategoryAppInfo *info) -{ - FUNCTIONSETUP; - - if (!info) - { - WARNINGKPILOT << "Dumping bad pointer." << endl; - return; - } - - DEBUGKPILOT << fname << " lastUniqueId: " - << (int) info->lastUniqueID << endl; - for (unsigned int i = 0; i < CATEGORY_COUNT; i++) - { - if (!info->name[i][0]) continue; - DEBUGKPILOT << fname << ": " << i << " = " - << (int)(info->ID[i]) << " <" - << info->name[i] << ">" << endl; - } -} - - -} - - diff --git a/lib/pilot.cpp b/lib/pilot.cpp new file mode 100644 index 0000000..d946593 --- /dev/null +++ b/lib/pilot.cpp @@ -0,0 +1,264 @@ +/* pilot.cpp KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** Copyright (C) 2003-2006 Adriaan de Groot +** +** These are the base class structures that reside on the +** handheld device -- databases and their parts. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 +#include +#include +#include + +#include "pilot.h" +#include "pilotDatabase.h" +#include "pilotAppInfo.h" +#include "pilotRecord.h" + + +namespace Pilot +{ +static TQTextCodec *codec = 0L; +static TQMutex* mutex = 0L; + + +TQString fromPilot( const char *c, int len ) +{ + mutex->lock(); + TQString str = codec->toUnicode(c,len); + mutex->unlock(); + return str; +} + +TQString fromPilot( const char *c ) +{ + mutex->lock(); + TQString str = codec->toUnicode(c); + mutex->unlock(); + return str; +} + +TQCString toPilot( const TQString &s ) +{ + mutex->lock(); + TQCString str = codec->fromUnicode(s); + mutex->unlock(); + return str; +} + +int toPilot( const TQString &s, char *buf, int len) +{ + mutex->lock(); + // See toPilot() below. + memset( buf, 0, len ); + int used = len; + TQCString cbuf = codec->fromUnicode(s,used); + if (used > len) + { + used=len; + } + memcpy( buf, cbuf.data(), used ); + mutex->unlock(); + return used; +} + +int toPilot( const TQString &s, unsigned char *buf, int len) +{ + mutex->lock(); + // Clear the buffer + memset( buf, 0, len ); + + // Convert to 8-bit encoding + int used = len; + TQCString cbuf = codec->fromUnicode(s,used); + + // Will it fit in the buffer? + if (used > len) + { + // Ought to be impossible, anyway, since 8-bit encodings + // are shorter than the UTF-8 encodings (1 byte per character + // vs. 1-or-more byte per character). + used=len; + } + + // Fill the buffer with encoded data. + memcpy( buf, cbuf.data(), used ); + mutex->unlock(); + return used; +} + +bool setupPilotCodec(const TQString &s) +{ + FUNCTIONSETUP; + mutex = new TQMutex(); + mutex->lock(); + TQString encoding(TDEGlobal::charsets()->encodingForName(s)); + + DEBUGKPILOT << fname << ": Using codec name " << s << endl; + DEBUGKPILOT << fname << ": Creating codec " << encoding << endl; + + // if the desired codec can't be found, latin1 will be returned anyway, no need to do this manually + codec = TDEGlobal::charsets()->codecForName(encoding); + + if (codec) + { + DEBUGKPILOT << fname << ": Got codec " << codec->name() << endl; + } + + mutex->unlock(); + return codec; +} + +TQString codecName() +{ + return TQString::fromLatin1(codec->name()); +} + +TQString category(const struct CategoryAppInfo *info, unsigned int i) +{ + if (!info || (i>=CATEGORY_COUNT)) + { + return TQString(); + } + + mutex->lock(); + TQString str = codec->toUnicode(info->name[i], + MIN(strlen(info->name[i]), CATEGORY_SIZE-1)); + mutex->unlock(); + return str; +} + + +int findCategory(const struct CategoryAppInfo *info, + const TQString &selectedCategory, + bool unknownIsUnfiled) +{ + FUNCTIONSETUP; + + if (!info) + { + WARNINGKPILOT << "Bad CategoryAppInfo pointer" << endl; + return -1; + } + + int currentCatID = -1; + for (unsigned int i=0; iname[i][0]) continue; + if (selectedCategory == category(info, i)) + { + currentCatID = i; + break; + } + } + + if (-1 == currentCatID) + { + DEBUGKPILOT << fname << ": Category name " + << selectedCategory << " not found." << endl; + } + else + { + DEBUGKPILOT << fname << ": Matched category " << currentCatID << endl; + } + + if ((currentCatID == -1) && unknownIsUnfiled) + currentCatID = 0; + return currentCatID; +} + +int insertCategory(struct CategoryAppInfo *info, + const TQString &label, + bool unknownIsUnfiled) +{ + FUNCTIONSETUP; + + if (!info) + { + WARNINGKPILOT << "Bad CategoryAppInfo pointer" << endl; + return -1; + } + + + int c = findCategory(info,label,unknownIsUnfiled); + if (c<0) + { + // This is the case when the category is not known + // and unknownIsUnfiled is false. + for (unsigned int i=0; iname[i][0]) + { + c = i; + break; + } + } + + if ((c>0) && (c < (int)CATEGORY_COUNT)) + { + // 0 is always unfiled, can't change that. + toPilot(label,info->name[c],CATEGORY_SIZE); + } + else + { + WARNINGKPILOT << "Category name " + << label + << " could not be added." << endl; + c = -1; + } + } + + return c; +} + +void dumpCategories(const struct CategoryAppInfo *info) +{ + FUNCTIONSETUP; + + if (!info) + { + WARNINGKPILOT << "Dumping bad pointer." << endl; + return; + } + + DEBUGKPILOT << fname << " lastUniqueId: " + << (int) info->lastUniqueID << endl; + for (unsigned int i = 0; i < CATEGORY_COUNT; i++) + { + if (!info->name[i][0]) continue; + DEBUGKPILOT << fname << ": " << i << " = " + << (int)(info->ID[i]) << " <" + << info->name[i] << ">" << endl; + } +} + + +} + + diff --git a/lib/pilotAddress.cc b/lib/pilotAddress.cc deleted file mode 100644 index 0706a39..0000000 --- a/lib/pilotAddress.cc +++ /dev/null @@ -1,636 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** Copyright (C) 2007 by Adriaan de Groot -** -** This is a C++ wrapper for the pilot's address database structures. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 -#include - -#include -#include - -#include "pilotAddress.h" - -static const char *default_address_category_names[] = { - "Unfiled", - "Business", - "Personal", - "Quicklist", - 0L -} ; - -static const char *default_address_field_labels[] = { - "Last name", - "First name", - "Company", - "Work", - "Home", - "Fax", - "Other", - "E-mail", - "Addr(W)", - "City", - "State", - "Zip Code", - "Country", - "Title", - "Custom 1", - "Custom 2", - "Custom 3", - "Custom 4", - "Note", - 0L -} ; - -void PilotAddressInfo::resetToDefault() -{ - FUNCTIONSETUP; - // Reset to all 0s - memset(&fInfo,0,sizeof(fInfo)); - // Fill up default categories - for (unsigned int i=0; (i<4) && default_address_category_names[i]; ++i) - { - strncpy(fInfo.category.name[i],default_address_category_names[i],sizeof(fInfo.category.name[0])); - } - // Weird hack, looks like there's an extra copy of Unfiled - strncpy(fInfo.category.name[15],default_address_category_names[0],sizeof(fInfo.category.name[0])); - - // And fill up the default labels. - for (unsigned int i=0; (i<19) && default_address_field_labels[i]; ++i) - { - strncpy(fInfo.labels[i],default_address_field_labels[i],sizeof(fInfo.labels[0])); - } -} - -TQString PilotAddressInfo::phoneLabel(EPhoneType i) const -{ - if (i<=eMobile) - { - return Pilot::fromPilot(info()->phoneLabels[i]); - } - else - { - return TQString(); - } -} - -PhoneSlot::PhoneSlot( const int v ) -{ - i = entryPhone1; - operator=(v); -} - -const PhoneSlot &PhoneSlot::operator=( const int &v ) -{ - if ( (entryPhone1 <= v) && (v <= entryPhone5) ) - { - i = v; - } - else - { - i = invalid; - } - return *this; -} - -const PhoneSlot &PhoneSlot::operator++() -{ - if ( (i!=invalid) && (idata(); - b.allocated = b.used = rec->size(); - unpack_Address(&fAddressInfo, &b, address_v1); - } - else - { - fAddressInfo.phoneLabel[0] = (int) PilotAddressInfo::eWork; - fAddressInfo.phoneLabel[1] = (int) PilotAddressInfo::eHome; - fAddressInfo.phoneLabel[2] = (int) PilotAddressInfo::eOther; - fAddressInfo.phoneLabel[3] = (int) PilotAddressInfo::eMobile; - fAddressInfo.phoneLabel[4] = (int) PilotAddressInfo::eEmail; - } -} - -PilotAddress::PilotAddress(const PilotAddress & copyFrom) : - PilotRecordBase(copyFrom), - fAddressInfo() -{ - FUNCTIONSETUPL(4); - _copyAddressInfo(copyFrom.fAddressInfo); -} - -PilotAddress & PilotAddress::operator = (const PilotAddress & copyFrom) -{ - FUNCTIONSETUPL(4); - PilotRecordBase::operator = (copyFrom); - _copyAddressInfo(copyFrom.fAddressInfo); - return *this; -} - -bool PilotAddress::operator==(const PilotAddress &compareTo) -{ - FUNCTIONSETUPL(4); - - // now compare all the fields stored in the fAddressInfo.entry array of char*[19] - for (int i=0; i"): TQString(); - TQString ps = (richText==TQt::RichText) ?CSL1("

"):CSL1("\n"); - TQString br = (richText==TQt::RichText) ?CSL1("
"):CSL1("\n"); - - // title + name - text += par; - if (!getField(entryTitle).isEmpty()) - { - text += rtExpand(getField(entryTitle), richText); - text += CSL1(" "); - } - - tmp = richText ? CSL1("%1 %2") : CSL1("%1 %2"); - TQString firstName = getField(entryFirstname); - if (firstName.isEmpty()) - { - // So replace placeholder for first name (%1) with empty - tmp = tmp.arg(TQString()); - } - else - { - tmp = tmp.arg(rtExpand(firstName,richText)); - } - tmp=tmp.arg(rtExpand(getField(entryLastname), richText)); - text += tmp; - text += ps; - - // company - if (!getField(entryCompany).isEmpty()) - { - text += par; - text += rtExpand(getField(entryCompany), richText); - text += ps; - } - - // phone numbers (+ labels) - text += par; - for ( PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i ) - { - if (!getField(i.toField()).isEmpty()) - { - if (richText) - { - if (getShownPhone() == i) - { - tmp=CSL1("%1: %2"); - } - else - { - tmp=CSL1("%1: %2"); - } - } - else - { - tmp=CSL1("%1: %2"); - } - if (info) - { - tmp=tmp.arg(info->phoneLabel( getPhoneType( i ) )); - } - else - { - tmp=tmp.arg(CSL1("Contact: ")); - } - tmp=tmp.arg(rtExpand(getField(i.toField()), richText)); - text += tmp; - text += br; - } - } - text += ps; - - // address, city, state, country - text += par; - if (!getField(entryAddress).isEmpty()) - { - text += rtExpand(getField(entryAddress), richText); - text += br; - } - if (!getField(entryCity).isEmpty()) - { - text += rtExpand(getField(entryCity), richText); - text += CSL1(" "); - } - if (!getField(entryState).isEmpty()) - { - text += rtExpand(getField(entryState), richText); - text += CSL1(" "); - } - if (!getField(entryZip).isEmpty()) - { - text += rtExpand(getField(entryZip), richText); - } - text += br; - if (!getField(entryCountry).isEmpty()) - { - text += rtExpand(getField(entryCountry), richText); - text += br; - } - text += ps; - - // custom fields - text += par; - for (int i = entryCustom1; i <= entryCustom4; i++) - { - if (!getField(i).isEmpty()) - { - text += rtExpand(getField(i), richText); - text += br; - } - } - text += ps; - - // category - if (info) - { - TQString categoryName = info->categoryName( category() ); - if (!categoryName.isEmpty()) - { - text += par; - text += rtExpand(categoryName, richText); - text += ps; - } - } - - // note - if (!getField(entryNote).isEmpty()) - { - text += richText?CSL1("
"):CSL1("-----------------------------\n"); - text += par; - text += rtExpand(getField(entryNote), richText); - text += ps; - } - - return text; -} - -TQStringList PilotAddress::getEmails() const -{ - TQStringList list; - - for ( PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i) - { - PilotAddressInfo::EPhoneType t = getPhoneType( i ); - if ( t == PilotAddressInfo::eEmail ) - { - TQString s = getField(i.toField()); - if (!s.isEmpty()) - { - list.append(s); - } - } - } - - return list; -} - -void PilotAddress::setEmails(const TQStringList &list) -{ - FUNCTIONSETUPL(4); - TQString test; - - // clear all e-mails first - for ( PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i ) - { - PilotAddressInfo::EPhoneType t = getPhoneType( i ); - if (t == PilotAddressInfo::eEmail) - { - setField(i.toField(), TQString() ); - } - } - - for(TQStringList::ConstIterator listIter = list.begin(); - listIter != list.end(); ++listIter) - { - TQString email = *listIter; - if (!setPhoneField(PilotAddressInfo::eEmail, email, NoFlags).isValid()) - { - WARNINGKPILOT << "Email accounts overflowed, silently dropped." << endl; - } - } -} - -TQString PilotAddress::getField(int field) const -{ - if ( (entryLastname <= field) && (field <= entryNote) ) - { - return Pilot::fromPilot(fAddressInfo.entry[field]); - } - else - { - return TQString(); - } -} - -PhoneSlot PilotAddress::_getNextEmptyPhoneSlot() const -{ - FUNCTIONSETUPL(4); - for (PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i) - { - const char *phoneField = getFieldP(i.toField()); - - if (!phoneField || !phoneField[0]) - { - return i; - } - } - return PhoneSlot(); -} - -PhoneSlot PilotAddress::setPhoneField(PilotAddressInfo::EPhoneType type, - const TQString &field, - PhoneHandlingFlags flags) -{ - FUNCTIONSETUPL(4); - - const bool overwriteExisting = (flags == Replace); - PhoneSlot fieldSlot; - if (overwriteExisting) - { - fieldSlot = _findPhoneFieldSlot(type); - } - - if ( !fieldSlot.isValid() ) - { - fieldSlot = _getNextEmptyPhoneSlot(); - } - - // store the overflow phone - if ( !fieldSlot.isValid() ) - { - DEBUGKPILOT << fname << ": Phone would overflow." << endl; - } - else // phone field 1 - 5; straight forward storage - { - setField(fieldSlot.toField(), field); - fAddressInfo.phoneLabel[fieldSlot.toOffset()] = (int) type; - } - return fieldSlot; -} - -PhoneSlot PilotAddress::_findPhoneFieldSlot(PilotAddressInfo::EPhoneType t) const -{ - FUNCTIONSETUPL(4); - for ( PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i ) - { - if ( getPhoneType(i) == t ) - { - return i; - } - } - - return PhoneSlot(); -} - -TQString PilotAddress::getPhoneField(PilotAddressInfo::EPhoneType type) const -{ - FUNCTIONSETUPL(4); - PhoneSlot fieldSlot = _findPhoneFieldSlot(type); - - if (fieldSlot.isValid()) - { - return getField(fieldSlot.toField()); - } - - return TQString(); -} - -PhoneSlot PilotAddress::getShownPhone() const -{ - // The slot is stored as an offset - return PhoneSlot(entryPhone1 + fAddressInfo.showPhone); -} - -const PhoneSlot &PilotAddress::setShownPhone( const PhoneSlot &v ) -{ - FUNCTIONSETUPL(4); - if (v.isValid()) - { - fAddressInfo.showPhone = v.toOffset(); - } - return v; -} - -PhoneSlot PilotAddress::setShownPhone(PilotAddressInfo::EPhoneType type) -{ - FUNCTIONSETUPL(4); - PhoneSlot fieldSlot = _findPhoneFieldSlot(type); - - // Did we find a slot with the requested type? - if (!fieldSlot.isValid()) - { - // No, so look for first non-empty phone slot - for ( fieldSlot = PhoneSlot::begin(); fieldSlot.isValid(); ++fieldSlot ) - { - const char *p = getFieldP(fieldSlot.toField()); - if (p && p[0]) - { - break; - } - } - // If all of them are empty, then use first slot instead - if (!fieldSlot.isValid()) - { - fieldSlot = PhoneSlot::begin(); - } - } - setShownPhone(fieldSlot); - return fieldSlot; -} - -PilotAddressInfo::EPhoneType PilotAddress::getPhoneType( const PhoneSlot &field ) const -{ - if ( field.isValid() ) - { - return (PilotAddressInfo::EPhoneType) fAddressInfo.phoneLabel[field.toOffset()]; - } - else - { - return PilotAddressInfo::eNone; - } -} - -void PilotAddress::setField(int field, const TQString &text) -{ - FUNCTIONSETUPL(4); - // This will have either been created with unpack_Address, and/or will - // be released with free_Address, so use malloc/free here: - if (fAddressInfo.entry[field]) - { - free(fAddressInfo.entry[field]); - fAddressInfo.entry[field]=0L; - } - if (!text.isEmpty()) - { - fAddressInfo.entry[field] = (char *) malloc(text.length() + 1); - Pilot::toPilot(text, fAddressInfo.entry[field], text.length()+1); - } - else - { - fAddressInfo.entry[field] = 0L; - } -} - -PilotRecord *PilotAddress::pack() const -{ - FUNCTIONSETUPL(4); - int i; - - pi_buffer_t *b = pi_buffer_new( sizeof(fAddressInfo) ); - i = pack_Address(const_cast(&fAddressInfo), b, address_v1); - if (i<0) - { - return 0L; - } - // pack_Address sets b->used - return new PilotRecord( b, this ); -} diff --git a/lib/pilotAddress.cpp b/lib/pilotAddress.cpp new file mode 100644 index 0000000..0706a39 --- /dev/null +++ b/lib/pilotAddress.cpp @@ -0,0 +1,636 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** Copyright (C) 2007 by Adriaan de Groot +** +** This is a C++ wrapper for the pilot's address database structures. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 +#include + +#include +#include + +#include "pilotAddress.h" + +static const char *default_address_category_names[] = { + "Unfiled", + "Business", + "Personal", + "Quicklist", + 0L +} ; + +static const char *default_address_field_labels[] = { + "Last name", + "First name", + "Company", + "Work", + "Home", + "Fax", + "Other", + "E-mail", + "Addr(W)", + "City", + "State", + "Zip Code", + "Country", + "Title", + "Custom 1", + "Custom 2", + "Custom 3", + "Custom 4", + "Note", + 0L +} ; + +void PilotAddressInfo::resetToDefault() +{ + FUNCTIONSETUP; + // Reset to all 0s + memset(&fInfo,0,sizeof(fInfo)); + // Fill up default categories + for (unsigned int i=0; (i<4) && default_address_category_names[i]; ++i) + { + strncpy(fInfo.category.name[i],default_address_category_names[i],sizeof(fInfo.category.name[0])); + } + // Weird hack, looks like there's an extra copy of Unfiled + strncpy(fInfo.category.name[15],default_address_category_names[0],sizeof(fInfo.category.name[0])); + + // And fill up the default labels. + for (unsigned int i=0; (i<19) && default_address_field_labels[i]; ++i) + { + strncpy(fInfo.labels[i],default_address_field_labels[i],sizeof(fInfo.labels[0])); + } +} + +TQString PilotAddressInfo::phoneLabel(EPhoneType i) const +{ + if (i<=eMobile) + { + return Pilot::fromPilot(info()->phoneLabels[i]); + } + else + { + return TQString(); + } +} + +PhoneSlot::PhoneSlot( const int v ) +{ + i = entryPhone1; + operator=(v); +} + +const PhoneSlot &PhoneSlot::operator=( const int &v ) +{ + if ( (entryPhone1 <= v) && (v <= entryPhone5) ) + { + i = v; + } + else + { + i = invalid; + } + return *this; +} + +const PhoneSlot &PhoneSlot::operator++() +{ + if ( (i!=invalid) && (idata(); + b.allocated = b.used = rec->size(); + unpack_Address(&fAddressInfo, &b, address_v1); + } + else + { + fAddressInfo.phoneLabel[0] = (int) PilotAddressInfo::eWork; + fAddressInfo.phoneLabel[1] = (int) PilotAddressInfo::eHome; + fAddressInfo.phoneLabel[2] = (int) PilotAddressInfo::eOther; + fAddressInfo.phoneLabel[3] = (int) PilotAddressInfo::eMobile; + fAddressInfo.phoneLabel[4] = (int) PilotAddressInfo::eEmail; + } +} + +PilotAddress::PilotAddress(const PilotAddress & copyFrom) : + PilotRecordBase(copyFrom), + fAddressInfo() +{ + FUNCTIONSETUPL(4); + _copyAddressInfo(copyFrom.fAddressInfo); +} + +PilotAddress & PilotAddress::operator = (const PilotAddress & copyFrom) +{ + FUNCTIONSETUPL(4); + PilotRecordBase::operator = (copyFrom); + _copyAddressInfo(copyFrom.fAddressInfo); + return *this; +} + +bool PilotAddress::operator==(const PilotAddress &compareTo) +{ + FUNCTIONSETUPL(4); + + // now compare all the fields stored in the fAddressInfo.entry array of char*[19] + for (int i=0; i"): TQString(); + TQString ps = (richText==TQt::RichText) ?CSL1("

"):CSL1("\n"); + TQString br = (richText==TQt::RichText) ?CSL1("
"):CSL1("\n"); + + // title + name + text += par; + if (!getField(entryTitle).isEmpty()) + { + text += rtExpand(getField(entryTitle), richText); + text += CSL1(" "); + } + + tmp = richText ? CSL1("%1 %2") : CSL1("%1 %2"); + TQString firstName = getField(entryFirstname); + if (firstName.isEmpty()) + { + // So replace placeholder for first name (%1) with empty + tmp = tmp.arg(TQString()); + } + else + { + tmp = tmp.arg(rtExpand(firstName,richText)); + } + tmp=tmp.arg(rtExpand(getField(entryLastname), richText)); + text += tmp; + text += ps; + + // company + if (!getField(entryCompany).isEmpty()) + { + text += par; + text += rtExpand(getField(entryCompany), richText); + text += ps; + } + + // phone numbers (+ labels) + text += par; + for ( PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i ) + { + if (!getField(i.toField()).isEmpty()) + { + if (richText) + { + if (getShownPhone() == i) + { + tmp=CSL1("%1: %2"); + } + else + { + tmp=CSL1("%1: %2"); + } + } + else + { + tmp=CSL1("%1: %2"); + } + if (info) + { + tmp=tmp.arg(info->phoneLabel( getPhoneType( i ) )); + } + else + { + tmp=tmp.arg(CSL1("Contact: ")); + } + tmp=tmp.arg(rtExpand(getField(i.toField()), richText)); + text += tmp; + text += br; + } + } + text += ps; + + // address, city, state, country + text += par; + if (!getField(entryAddress).isEmpty()) + { + text += rtExpand(getField(entryAddress), richText); + text += br; + } + if (!getField(entryCity).isEmpty()) + { + text += rtExpand(getField(entryCity), richText); + text += CSL1(" "); + } + if (!getField(entryState).isEmpty()) + { + text += rtExpand(getField(entryState), richText); + text += CSL1(" "); + } + if (!getField(entryZip).isEmpty()) + { + text += rtExpand(getField(entryZip), richText); + } + text += br; + if (!getField(entryCountry).isEmpty()) + { + text += rtExpand(getField(entryCountry), richText); + text += br; + } + text += ps; + + // custom fields + text += par; + for (int i = entryCustom1; i <= entryCustom4; i++) + { + if (!getField(i).isEmpty()) + { + text += rtExpand(getField(i), richText); + text += br; + } + } + text += ps; + + // category + if (info) + { + TQString categoryName = info->categoryName( category() ); + if (!categoryName.isEmpty()) + { + text += par; + text += rtExpand(categoryName, richText); + text += ps; + } + } + + // note + if (!getField(entryNote).isEmpty()) + { + text += richText?CSL1("
"):CSL1("-----------------------------\n"); + text += par; + text += rtExpand(getField(entryNote), richText); + text += ps; + } + + return text; +} + +TQStringList PilotAddress::getEmails() const +{ + TQStringList list; + + for ( PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i) + { + PilotAddressInfo::EPhoneType t = getPhoneType( i ); + if ( t == PilotAddressInfo::eEmail ) + { + TQString s = getField(i.toField()); + if (!s.isEmpty()) + { + list.append(s); + } + } + } + + return list; +} + +void PilotAddress::setEmails(const TQStringList &list) +{ + FUNCTIONSETUPL(4); + TQString test; + + // clear all e-mails first + for ( PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i ) + { + PilotAddressInfo::EPhoneType t = getPhoneType( i ); + if (t == PilotAddressInfo::eEmail) + { + setField(i.toField(), TQString() ); + } + } + + for(TQStringList::ConstIterator listIter = list.begin(); + listIter != list.end(); ++listIter) + { + TQString email = *listIter; + if (!setPhoneField(PilotAddressInfo::eEmail, email, NoFlags).isValid()) + { + WARNINGKPILOT << "Email accounts overflowed, silently dropped." << endl; + } + } +} + +TQString PilotAddress::getField(int field) const +{ + if ( (entryLastname <= field) && (field <= entryNote) ) + { + return Pilot::fromPilot(fAddressInfo.entry[field]); + } + else + { + return TQString(); + } +} + +PhoneSlot PilotAddress::_getNextEmptyPhoneSlot() const +{ + FUNCTIONSETUPL(4); + for (PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i) + { + const char *phoneField = getFieldP(i.toField()); + + if (!phoneField || !phoneField[0]) + { + return i; + } + } + return PhoneSlot(); +} + +PhoneSlot PilotAddress::setPhoneField(PilotAddressInfo::EPhoneType type, + const TQString &field, + PhoneHandlingFlags flags) +{ + FUNCTIONSETUPL(4); + + const bool overwriteExisting = (flags == Replace); + PhoneSlot fieldSlot; + if (overwriteExisting) + { + fieldSlot = _findPhoneFieldSlot(type); + } + + if ( !fieldSlot.isValid() ) + { + fieldSlot = _getNextEmptyPhoneSlot(); + } + + // store the overflow phone + if ( !fieldSlot.isValid() ) + { + DEBUGKPILOT << fname << ": Phone would overflow." << endl; + } + else // phone field 1 - 5; straight forward storage + { + setField(fieldSlot.toField(), field); + fAddressInfo.phoneLabel[fieldSlot.toOffset()] = (int) type; + } + return fieldSlot; +} + +PhoneSlot PilotAddress::_findPhoneFieldSlot(PilotAddressInfo::EPhoneType t) const +{ + FUNCTIONSETUPL(4); + for ( PhoneSlot i = PhoneSlot::begin(); i.isValid(); ++i ) + { + if ( getPhoneType(i) == t ) + { + return i; + } + } + + return PhoneSlot(); +} + +TQString PilotAddress::getPhoneField(PilotAddressInfo::EPhoneType type) const +{ + FUNCTIONSETUPL(4); + PhoneSlot fieldSlot = _findPhoneFieldSlot(type); + + if (fieldSlot.isValid()) + { + return getField(fieldSlot.toField()); + } + + return TQString(); +} + +PhoneSlot PilotAddress::getShownPhone() const +{ + // The slot is stored as an offset + return PhoneSlot(entryPhone1 + fAddressInfo.showPhone); +} + +const PhoneSlot &PilotAddress::setShownPhone( const PhoneSlot &v ) +{ + FUNCTIONSETUPL(4); + if (v.isValid()) + { + fAddressInfo.showPhone = v.toOffset(); + } + return v; +} + +PhoneSlot PilotAddress::setShownPhone(PilotAddressInfo::EPhoneType type) +{ + FUNCTIONSETUPL(4); + PhoneSlot fieldSlot = _findPhoneFieldSlot(type); + + // Did we find a slot with the requested type? + if (!fieldSlot.isValid()) + { + // No, so look for first non-empty phone slot + for ( fieldSlot = PhoneSlot::begin(); fieldSlot.isValid(); ++fieldSlot ) + { + const char *p = getFieldP(fieldSlot.toField()); + if (p && p[0]) + { + break; + } + } + // If all of them are empty, then use first slot instead + if (!fieldSlot.isValid()) + { + fieldSlot = PhoneSlot::begin(); + } + } + setShownPhone(fieldSlot); + return fieldSlot; +} + +PilotAddressInfo::EPhoneType PilotAddress::getPhoneType( const PhoneSlot &field ) const +{ + if ( field.isValid() ) + { + return (PilotAddressInfo::EPhoneType) fAddressInfo.phoneLabel[field.toOffset()]; + } + else + { + return PilotAddressInfo::eNone; + } +} + +void PilotAddress::setField(int field, const TQString &text) +{ + FUNCTIONSETUPL(4); + // This will have either been created with unpack_Address, and/or will + // be released with free_Address, so use malloc/free here: + if (fAddressInfo.entry[field]) + { + free(fAddressInfo.entry[field]); + fAddressInfo.entry[field]=0L; + } + if (!text.isEmpty()) + { + fAddressInfo.entry[field] = (char *) malloc(text.length() + 1); + Pilot::toPilot(text, fAddressInfo.entry[field], text.length()+1); + } + else + { + fAddressInfo.entry[field] = 0L; + } +} + +PilotRecord *PilotAddress::pack() const +{ + FUNCTIONSETUPL(4); + int i; + + pi_buffer_t *b = pi_buffer_new( sizeof(fAddressInfo) ); + i = pack_Address(const_cast(&fAddressInfo), b, address_v1); + if (i<0) + { + return 0L; + } + // pack_Address sets b->used + return new PilotRecord( b, this ); +} diff --git a/lib/pilotAppInfo.cc b/lib/pilotAppInfo.cc deleted file mode 100644 index 5edc571..0000000 --- a/lib/pilotAppInfo.cc +++ /dev/null @@ -1,77 +0,0 @@ -/* pilotAppInfo.cc KPilot -** -** Copyright (C) 2005-2006 Adriaan de Groot -** -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 - -#include "pilotAppInfo.h" - -PilotAppInfoBase::PilotAppInfoBase(PilotDatabase *d) : - fC( 0L ), - fLen(0), - fOwn(true) -{ - FUNCTIONSETUP; - int appLen = Pilot::MAX_APPINFO_SIZE; - unsigned char buffer[Pilot::MAX_APPINFO_SIZE]; - - if (!d || !d->isOpen()) - { - WARNINGKPILOT << "Bad database pointer." << endl; - fLen = 0; - KPILOT_DELETE( fC ); - return; - } - - fC = new struct CategoryAppInfo; - fLen = appLen = d->readAppBlock(buffer,appLen); - unpack_CategoryAppInfo(fC, buffer, appLen); -} - -PilotAppInfoBase::~PilotAppInfoBase() -{ - if (fOwn) - { - delete fC; - } -} - -bool PilotAppInfoBase::setCategoryName(unsigned int i, const TQString &s) -{ - if ( (i>=Pilot::CATEGORY_COUNT) || // bad category number - (!categoryInfo())) // Nowhere to write to - { - return false; - } - - (void) Pilot::toPilot(s, categoryInfo()->name[i], Pilot::CATEGORY_SIZE - 1); - return true; -} - - diff --git a/lib/pilotAppInfo.cpp b/lib/pilotAppInfo.cpp new file mode 100644 index 0000000..777dcc7 --- /dev/null +++ b/lib/pilotAppInfo.cpp @@ -0,0 +1,77 @@ +/* pilotAppInfo.cpp KPilot +** +** Copyright (C) 2005-2006 Adriaan de Groot +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 + +#include "pilotAppInfo.h" + +PilotAppInfoBase::PilotAppInfoBase(PilotDatabase *d) : + fC( 0L ), + fLen(0), + fOwn(true) +{ + FUNCTIONSETUP; + int appLen = Pilot::MAX_APPINFO_SIZE; + unsigned char buffer[Pilot::MAX_APPINFO_SIZE]; + + if (!d || !d->isOpen()) + { + WARNINGKPILOT << "Bad database pointer." << endl; + fLen = 0; + KPILOT_DELETE( fC ); + return; + } + + fC = new struct CategoryAppInfo; + fLen = appLen = d->readAppBlock(buffer,appLen); + unpack_CategoryAppInfo(fC, buffer, appLen); +} + +PilotAppInfoBase::~PilotAppInfoBase() +{ + if (fOwn) + { + delete fC; + } +} + +bool PilotAppInfoBase::setCategoryName(unsigned int i, const TQString &s) +{ + if ( (i>=Pilot::CATEGORY_COUNT) || // bad category number + (!categoryInfo())) // Nowhere to write to + { + return false; + } + + (void) Pilot::toPilot(s, categoryInfo()->name[i], Pilot::CATEGORY_SIZE - 1); + return true; +} + + diff --git a/lib/pilotDatabase.cc b/lib/pilotDatabase.cc deleted file mode 100644 index f4a1b40..0000000 --- a/lib/pilotDatabase.cc +++ /dev/null @@ -1,112 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** Copyright (C) 2005-2006 Adriaan de Groot -** -** This is the abstract base class for databases, which is used both -** by local databases and by the serial databases held in the Pilot. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 // Needed by pilot-link include -#include - -#include - -#include - -#include "pilotDatabase.h" -#include "pilotRecord.h" - -static int creationCount = 0; -static TQStringList *createdNames = 0L; - -PilotDatabase::PilotDatabase(const TQString &s) : - fDBOpen(false), - fName(s) -{ - FUNCTIONSETUP; - creationCount++; - if (!createdNames) - { - createdNames = new TQStringList(); - } - createdNames->append(s.isEmpty() ? CSL1("") : s); -} - -/* virtual */ PilotDatabase::~PilotDatabase() -{ - FUNCTIONSETUP; - creationCount--; - if (createdNames) - { - createdNames->remove(fName.isEmpty() ? CSL1("") : fName); - } -} - -/* static */ int PilotDatabase::instanceCount() -{ - FUNCTIONSETUP; - DEBUGKPILOT << fname << ": " << creationCount << " databases." << endl; - if (createdNames) - { - DEBUGKPILOT << fname << ": " - << createdNames->join(CSL1(",")) << endl; - } - return creationCount; -} - -/* virtual */ Pilot::RecordIDList PilotDatabase::idList() -{ - Pilot::RecordIDList l; - - for (unsigned int i = 0 ; ; i++) - { - PilotRecord *r = readRecordByIndex(i); - if (!r) break; - l.append(r->id()); - delete r; - } - - return l; -} - -/* virtual */ Pilot::RecordIDList PilotDatabase::modifiedIDList() -{ - Pilot::RecordIDList l; - - resetDBIndex(); - while(1) - { - PilotRecord *r = readNextModifiedRec(); - if (!r) break; - l.append(r->id()); - delete r; - } - - return l; -} - diff --git a/lib/pilotDatabase.cpp b/lib/pilotDatabase.cpp new file mode 100644 index 0000000..f4a1b40 --- /dev/null +++ b/lib/pilotDatabase.cpp @@ -0,0 +1,112 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** Copyright (C) 2005-2006 Adriaan de Groot +** +** This is the abstract base class for databases, which is used both +** by local databases and by the serial databases held in the Pilot. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 // Needed by pilot-link include +#include + +#include + +#include + +#include "pilotDatabase.h" +#include "pilotRecord.h" + +static int creationCount = 0; +static TQStringList *createdNames = 0L; + +PilotDatabase::PilotDatabase(const TQString &s) : + fDBOpen(false), + fName(s) +{ + FUNCTIONSETUP; + creationCount++; + if (!createdNames) + { + createdNames = new TQStringList(); + } + createdNames->append(s.isEmpty() ? CSL1("") : s); +} + +/* virtual */ PilotDatabase::~PilotDatabase() +{ + FUNCTIONSETUP; + creationCount--; + if (createdNames) + { + createdNames->remove(fName.isEmpty() ? CSL1("") : fName); + } +} + +/* static */ int PilotDatabase::instanceCount() +{ + FUNCTIONSETUP; + DEBUGKPILOT << fname << ": " << creationCount << " databases." << endl; + if (createdNames) + { + DEBUGKPILOT << fname << ": " + << createdNames->join(CSL1(",")) << endl; + } + return creationCount; +} + +/* virtual */ Pilot::RecordIDList PilotDatabase::idList() +{ + Pilot::RecordIDList l; + + for (unsigned int i = 0 ; ; i++) + { + PilotRecord *r = readRecordByIndex(i); + if (!r) break; + l.append(r->id()); + delete r; + } + + return l; +} + +/* virtual */ Pilot::RecordIDList PilotDatabase::modifiedIDList() +{ + Pilot::RecordIDList l; + + resetDBIndex(); + while(1) + { + PilotRecord *r = readNextModifiedRec(); + if (!r) break; + l.append(r->id()); + delete r; + } + + return l; +} + diff --git a/lib/pilotDateEntry.cc b/lib/pilotDateEntry.cc deleted file mode 100644 index 58da804..0000000 --- a/lib/pilotDateEntry.cc +++ /dev/null @@ -1,478 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** -** This is a C++ wrapper for the Pilot's datebook structures. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 - -#include -#include -#include - -#include - -#include "pilotDateEntry.h" - -static const char *default_date_category_names[] = { - "Unfiled", - "Business", - "Personal", - 0L -} ; - -void PilotDateInfo::resetToDefault() -{ - FUNCTIONSETUP; - // Reset to all 0s - memset(&fInfo,0,sizeof(fInfo)); - // Fill up default categories - for (unsigned int i=0; (i<4) && default_date_category_names[i]; ++i) - { - strncpy(fInfo.category.name[i],default_date_category_names[i],sizeof(fInfo.category.name[0])); - } - - fInfo.startOfWeek = 0; - -} - - -PilotDateEntry::PilotDateEntry():PilotRecordBase() -{ - ::memset(&fAppointmentInfo, 0, sizeof(struct Appointment)); -} - -/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDateEntry() -*/ -PilotDateEntry::PilotDateEntry(PilotRecord * rec) : - PilotRecordBase(rec) -{ - ::memset(&fAppointmentInfo, 0, sizeof(fAppointmentInfo)); - if (rec) - { - // Construct a fake pi_buffer for unpack_Appointment. - // No ownership changes occur here. - pi_buffer_t b = { (unsigned char *) rec->data(), rec->size(), rec->size() } ; - unpack_Appointment(&fAppointmentInfo, &b, datebook_v1); - } - return; - -} - -void PilotDateEntry::_copyExceptions(const PilotDateEntry & e) -{ - if (e.fAppointmentInfo.exceptions > 0) - { - size_t blocksize = e.fAppointmentInfo.exceptions * - sizeof(struct tm); - - fAppointmentInfo.exception = (struct tm *)::malloc(blocksize); - - if (fAppointmentInfo.exception) - { - fAppointmentInfo.exceptions = - e.fAppointmentInfo.exceptions; - ::memcpy(fAppointmentInfo.exception, - e.fAppointmentInfo.exception, blocksize); - } - else - { - WARNINGKPILOT << "malloc() failed, exceptions not copied" << endl; - fAppointmentInfo.exceptions = 0; - } - } - else - { - fAppointmentInfo.exceptions = 0; - fAppointmentInfo.exception = 0L; - } -} - - -PilotDateEntry::PilotDateEntry(const PilotDateEntry & e) : - PilotRecordBase(e) -{ - ::memcpy(&fAppointmentInfo, &e.fAppointmentInfo, - sizeof(struct Appointment)); - // See operator = for explanation - fAppointmentInfo.exception = 0L; - fAppointmentInfo.description = 0L; - fAppointmentInfo.note = 0L; - - _copyExceptions(e); - setDescriptionP(e.fAppointmentInfo.description); - setNoteP(e.fAppointmentInfo.note); -} - - -PilotDateEntry & PilotDateEntry::operator = (const PilotDateEntry & e) -{ - if (this != &e) // Pointer equality! - { - KPILOT_FREE(fAppointmentInfo.exception); - KPILOT_FREE(fAppointmentInfo.description); - KPILOT_FREE(fAppointmentInfo.note); - ::memcpy(&fAppointmentInfo, &e.fAppointmentInfo, - sizeof(fAppointmentInfo)); - - // The original pointers were already freed; since we're now - // got the pointers from the new structure and we're going - // to use the standard set functions make sure that - // we don't free() the copies-of-pointers from e, which - // would be disastrous. - // - // - fAppointmentInfo.exception = 0L; - fAppointmentInfo.description = 0L; - fAppointmentInfo.note = 0L; - - _copyExceptions(e); - setDescriptionP(e.fAppointmentInfo.description); - setNoteP(e.fAppointmentInfo.note); - } - - return *this; -} // end of assignment operator - - -TQString PilotDateEntry::getTextRepresentation(TQt::TextFormat richText) -{ - TQString text, tmp; - TQString par = (richText==TQt::RichText) ?CSL1("

"):TQString(); - TQString ps = (richText==TQt::RichText) ?CSL1("

"):CSL1("\n"); - TQString br = (richText==TQt::RichText) ?CSL1("
"):CSL1("\n"); - - // title + name - text += par; - tmp=richText?CSL1("%1"):CSL1("%1"); - text += tmp.arg(rtExpand(getDescription(), richText)); - text += ps; - - TQDateTime dt(readTm(getEventStart())); - TQString startDate(dt.toString(Qt::LocalDate)); - text+=par; - text+=i18n("Start date: %1").arg(startDate); - text+=ps; - - if (isEvent()) - { - text+=par; - text+=i18n("Whole-day event"); - text+=ps; - } - else - { - dt=readTm(getEventEnd()); - TQString endDate(dt.toString(Qt::LocalDate)); - text+=par; - text+=i18n("End date: %1").arg(endDate); - text+=ps; - } - - if ( isAlarmEnabled() ) - { - text+=par; - tmp=i18n("%1 is the duration, %2 is the time unit", "Alarm: %1 %2 before event starts"). - arg(getAdvance()); - switch (getAdvanceUnits()) - { - case advMinutes: tmp=tmp.arg(i18n("minutes")); break; - case advHours: tmp=tmp.arg(i18n("hours")); break; - case advDays: tmp=tmp.arg(i18n("days")); break; - default: tmp=tmp.arg(TQString()); break;; - } - text+=tmp; - text+=ps; - } - - if (getRepeatType() != repeatNone) - { - text+=par; - tmp=i18n("Recurrence: every %1 %2"); - int freq = getRepeatFrequency(); - tmp=tmp.arg(freq); - - switch(getRepeatType()) - { - case repeatDaily: tmp=tmp.arg(i18n("day(s)")); break; - case repeatWeekly: tmp=tmp.arg(i18n("week(s)")); break; - case repeatMonthlyByDay: - case repeatMonthlyByDate: tmp=tmp.arg(i18n("month(s)")); break; - case repeatYearly: tmp=tmp.arg(i18n("year(s)")); break; - default: tmp=tmp.arg(TQString()); break; - } - text+=tmp; - text+=br; - - bool repeatsForever = getRepeatForever(); - if (repeatsForever) - { - text+=i18n("Repeats indefinitely"); - } - else - { - dt = readTm(getRepeatEnd()).date(); - text+=i18n("Until %1").arg(dt.toString(Qt::LocalDate)); - } - text+=br; - - if (getRepeatType()==repeatMonthlyByDay) text+=i18n("Repeating on the i-th day of week j")+br; - if (getRepeatType()==repeatMonthlyByDate) text+=i18n("Repeating on the n-th day of the month")+br; - // TODO: show the dayArray when repeating weekly - /*TQBitArray dayArray(7); - if (getRepeatType()==repeatWeekly) text+=i18n("Repeat day flags: %1").arg(getRepeatDays - const int *days = dateEntry->getRepeatDays(); - // Rotate the days of the week, since day numbers on the Pilot and - // in vCal / Events are different. - if (days[0]) dayArray.setBit(6); - for (int i = 1; i < 7; i++) - { - if (days[i]) dayArray.setBit(i-1); - }*/ - text+=ps; - } - - if (getExceptionCount()>0 ) - { - text+=par; - text+=i18n("Exceptions:")+br; - for (int i = 0; i < getExceptionCount(); i++) - { - TQDate exdt=readTm(getExceptions()[i]).date(); - text+=exdt.toString(Qt::LocalDate); - text+=br; - } - text+=ps; - } - - if (!getNote().isEmpty()) - { - text += richText?CSL1("
"):CSL1("-------------------------\n"); - text+=par; - text+=richText?i18n("Note:
"):i18n("Note:\n"); - text+=rtExpand(getNote(), richText); - text+=ps; - } - - return text; -} - -TQDateTime PilotDateEntry::dtStart() const -{ - FUNCTIONSETUP; - return readTm( getEventStart() ); -} - -TQDateTime PilotDateEntry::dtEnd() const -{ - FUNCTIONSETUP; - return readTm( getEventEnd() ); -} - -TQDateTime PilotDateEntry::dtRepeatEnd() const -{ - FUNCTIONSETUP; - return readTm( getRepeatEnd() ); -} - -unsigned int PilotDateEntry::alarmLeadTime() const -{ - FUNCTIONSETUP; - if (!isAlarmEnabled()) return 0; - - int adv = getAdvance(); - if ( adv < 0 ) - { - return 0; // Not possible to enter on the pilot - } - unsigned int t = adv; - int u = getAdvanceUnits(); - - - switch(u) - { - case advMinutes : t *= 60; break; - case advHours : t *= 3600; break; - case advDays : t *= 3600 * 24; break; - default: t = 0; - } - - return t; -} - -PilotRecord *PilotDateEntry::pack() const -{ - int i; - - pi_buffer_t *b = pi_buffer_new( sizeof(fAppointmentInfo) ); - i = pack_Appointment(const_cast(&fAppointmentInfo), b, datebook_v1); - if (i<0) - { - // Generic error from the pack_*() functions. - return 0; - } - - // pack_Appointment sets b->used - return new PilotRecord( b, this ); -} - -/* setExceptions sets a new set of exceptions. Note that - PilotDateEntry assumes ownership of the array and will - delete the old one. */ -void PilotDateEntry::setExceptions(struct tm *e) { - if (fAppointmentInfo.exception != e) - { - KPILOT_FREE(fAppointmentInfo.exception); - } - fAppointmentInfo.exception=e; -} - - -void PilotDateEntry::setDescriptionP(const char *desc, int l) -{ - FUNCTIONSETUP; - KPILOT_FREE(fAppointmentInfo.description); - - if (desc && *desc) - { - if (-1 == l) l=::strlen(desc); - fAppointmentInfo.description = - (char *) ::malloc(l + 1); - if (fAppointmentInfo.description) - { - strlcpy(fAppointmentInfo.description, desc, l+1); - } - else - { - WARNINGKPILOT << "malloc() failed, description not set" << endl; - } - } - else - { - fAppointmentInfo.description = 0L; - } -} - -void PilotDateEntry::setNoteP(const char *note, int l) -{ - FUNCTIONSETUP; - KPILOT_FREE(fAppointmentInfo.note); - - if (note && *note) - { - if (-1 == l) l=::strlen(note); - fAppointmentInfo.note = (char *)::malloc(l + 1); - if (fAppointmentInfo.note) - { - strlcpy(fAppointmentInfo.note, note,l+1); - } - else - { - WARNINGKPILOT << "malloc() failed, note not set" << endl; - } - } - else - { - fAppointmentInfo.note = 0L; - } -} - -void PilotDateEntry::setNote(const TQString &s) -{ - TQCString t = Pilot::toPilot(s); - setNoteP( t.data(),t.length() ); -} - -void PilotDateEntry::setLocation(const TQString &s) -{ - TQString note = Pilot::fromPilot(getNoteP()); - TQRegExp rxp = TQRegExp("^[Ll]ocation:[^\n]+\n"); - - // per TQString docs, this covers null and 0 length - if( s.isEmpty() ) - { - note.replace(rxp,""); - } - else - { - TQString location = "Location: " + s + "\n"; - int pos = note.find(rxp); - - if(pos >= 0) - { - note.replace( rxp, location ); - } - else - { - note = location + note; - setNote( note ); - } - } -} - -TQString PilotDateEntry::getLocation() const -{ - // Read the complete note here and not the filtered - // one from PilotDateEntry::getNote(); - TQString note = Pilot::fromPilot(getNoteP()); - TQRegExp rxp = TQRegExp("^[Ll]ocation:[^\n]+\n"); - int pos = note.find(rxp, 0); - - if(pos >= 0) - { - TQString location = rxp.capturedTexts().first(); - rxp = TQRegExp("^[Ll]ocation:[\\s|\t]*"); - location.replace(rxp,""); - location.replace("\n", ""); - return location; - } - else - { - return ""; - } -} - -void PilotDateEntry::setDescription(const TQString &s) -{ - TQCString t = Pilot::toPilot(s); - setDescriptionP( t.data(),t.length() ); -} - -TQString PilotDateEntry::getNote() const -{ - TQString note = Pilot::fromPilot(getNoteP()); - TQRegExp rxp = TQRegExp("^[Ll]ocation:[^\n]+\n"); - note.replace(rxp, "" ); - return note; -} - -TQString PilotDateEntry::getDescription() const -{ - return Pilot::fromPilot(getDescriptionP()); -} - diff --git a/lib/pilotDateEntry.cpp b/lib/pilotDateEntry.cpp new file mode 100644 index 0000000..58da804 --- /dev/null +++ b/lib/pilotDateEntry.cpp @@ -0,0 +1,478 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** +** This is a C++ wrapper for the Pilot's datebook structures. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 + +#include +#include +#include + +#include + +#include "pilotDateEntry.h" + +static const char *default_date_category_names[] = { + "Unfiled", + "Business", + "Personal", + 0L +} ; + +void PilotDateInfo::resetToDefault() +{ + FUNCTIONSETUP; + // Reset to all 0s + memset(&fInfo,0,sizeof(fInfo)); + // Fill up default categories + for (unsigned int i=0; (i<4) && default_date_category_names[i]; ++i) + { + strncpy(fInfo.category.name[i],default_date_category_names[i],sizeof(fInfo.category.name[0])); + } + + fInfo.startOfWeek = 0; + +} + + +PilotDateEntry::PilotDateEntry():PilotRecordBase() +{ + ::memset(&fAppointmentInfo, 0, sizeof(struct Appointment)); +} + +/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDateEntry() +*/ +PilotDateEntry::PilotDateEntry(PilotRecord * rec) : + PilotRecordBase(rec) +{ + ::memset(&fAppointmentInfo, 0, sizeof(fAppointmentInfo)); + if (rec) + { + // Construct a fake pi_buffer for unpack_Appointment. + // No ownership changes occur here. + pi_buffer_t b = { (unsigned char *) rec->data(), rec->size(), rec->size() } ; + unpack_Appointment(&fAppointmentInfo, &b, datebook_v1); + } + return; + +} + +void PilotDateEntry::_copyExceptions(const PilotDateEntry & e) +{ + if (e.fAppointmentInfo.exceptions > 0) + { + size_t blocksize = e.fAppointmentInfo.exceptions * + sizeof(struct tm); + + fAppointmentInfo.exception = (struct tm *)::malloc(blocksize); + + if (fAppointmentInfo.exception) + { + fAppointmentInfo.exceptions = + e.fAppointmentInfo.exceptions; + ::memcpy(fAppointmentInfo.exception, + e.fAppointmentInfo.exception, blocksize); + } + else + { + WARNINGKPILOT << "malloc() failed, exceptions not copied" << endl; + fAppointmentInfo.exceptions = 0; + } + } + else + { + fAppointmentInfo.exceptions = 0; + fAppointmentInfo.exception = 0L; + } +} + + +PilotDateEntry::PilotDateEntry(const PilotDateEntry & e) : + PilotRecordBase(e) +{ + ::memcpy(&fAppointmentInfo, &e.fAppointmentInfo, + sizeof(struct Appointment)); + // See operator = for explanation + fAppointmentInfo.exception = 0L; + fAppointmentInfo.description = 0L; + fAppointmentInfo.note = 0L; + + _copyExceptions(e); + setDescriptionP(e.fAppointmentInfo.description); + setNoteP(e.fAppointmentInfo.note); +} + + +PilotDateEntry & PilotDateEntry::operator = (const PilotDateEntry & e) +{ + if (this != &e) // Pointer equality! + { + KPILOT_FREE(fAppointmentInfo.exception); + KPILOT_FREE(fAppointmentInfo.description); + KPILOT_FREE(fAppointmentInfo.note); + ::memcpy(&fAppointmentInfo, &e.fAppointmentInfo, + sizeof(fAppointmentInfo)); + + // The original pointers were already freed; since we're now + // got the pointers from the new structure and we're going + // to use the standard set functions make sure that + // we don't free() the copies-of-pointers from e, which + // would be disastrous. + // + // + fAppointmentInfo.exception = 0L; + fAppointmentInfo.description = 0L; + fAppointmentInfo.note = 0L; + + _copyExceptions(e); + setDescriptionP(e.fAppointmentInfo.description); + setNoteP(e.fAppointmentInfo.note); + } + + return *this; +} // end of assignment operator + + +TQString PilotDateEntry::getTextRepresentation(TQt::TextFormat richText) +{ + TQString text, tmp; + TQString par = (richText==TQt::RichText) ?CSL1("

"):TQString(); + TQString ps = (richText==TQt::RichText) ?CSL1("

"):CSL1("\n"); + TQString br = (richText==TQt::RichText) ?CSL1("
"):CSL1("\n"); + + // title + name + text += par; + tmp=richText?CSL1("%1"):CSL1("%1"); + text += tmp.arg(rtExpand(getDescription(), richText)); + text += ps; + + TQDateTime dt(readTm(getEventStart())); + TQString startDate(dt.toString(Qt::LocalDate)); + text+=par; + text+=i18n("Start date: %1").arg(startDate); + text+=ps; + + if (isEvent()) + { + text+=par; + text+=i18n("Whole-day event"); + text+=ps; + } + else + { + dt=readTm(getEventEnd()); + TQString endDate(dt.toString(Qt::LocalDate)); + text+=par; + text+=i18n("End date: %1").arg(endDate); + text+=ps; + } + + if ( isAlarmEnabled() ) + { + text+=par; + tmp=i18n("%1 is the duration, %2 is the time unit", "Alarm: %1 %2 before event starts"). + arg(getAdvance()); + switch (getAdvanceUnits()) + { + case advMinutes: tmp=tmp.arg(i18n("minutes")); break; + case advHours: tmp=tmp.arg(i18n("hours")); break; + case advDays: tmp=tmp.arg(i18n("days")); break; + default: tmp=tmp.arg(TQString()); break;; + } + text+=tmp; + text+=ps; + } + + if (getRepeatType() != repeatNone) + { + text+=par; + tmp=i18n("Recurrence: every %1 %2"); + int freq = getRepeatFrequency(); + tmp=tmp.arg(freq); + + switch(getRepeatType()) + { + case repeatDaily: tmp=tmp.arg(i18n("day(s)")); break; + case repeatWeekly: tmp=tmp.arg(i18n("week(s)")); break; + case repeatMonthlyByDay: + case repeatMonthlyByDate: tmp=tmp.arg(i18n("month(s)")); break; + case repeatYearly: tmp=tmp.arg(i18n("year(s)")); break; + default: tmp=tmp.arg(TQString()); break; + } + text+=tmp; + text+=br; + + bool repeatsForever = getRepeatForever(); + if (repeatsForever) + { + text+=i18n("Repeats indefinitely"); + } + else + { + dt = readTm(getRepeatEnd()).date(); + text+=i18n("Until %1").arg(dt.toString(Qt::LocalDate)); + } + text+=br; + + if (getRepeatType()==repeatMonthlyByDay) text+=i18n("Repeating on the i-th day of week j")+br; + if (getRepeatType()==repeatMonthlyByDate) text+=i18n("Repeating on the n-th day of the month")+br; + // TODO: show the dayArray when repeating weekly + /*TQBitArray dayArray(7); + if (getRepeatType()==repeatWeekly) text+=i18n("Repeat day flags: %1").arg(getRepeatDays + const int *days = dateEntry->getRepeatDays(); + // Rotate the days of the week, since day numbers on the Pilot and + // in vCal / Events are different. + if (days[0]) dayArray.setBit(6); + for (int i = 1; i < 7; i++) + { + if (days[i]) dayArray.setBit(i-1); + }*/ + text+=ps; + } + + if (getExceptionCount()>0 ) + { + text+=par; + text+=i18n("Exceptions:")+br; + for (int i = 0; i < getExceptionCount(); i++) + { + TQDate exdt=readTm(getExceptions()[i]).date(); + text+=exdt.toString(Qt::LocalDate); + text+=br; + } + text+=ps; + } + + if (!getNote().isEmpty()) + { + text += richText?CSL1("
"):CSL1("-------------------------\n"); + text+=par; + text+=richText?i18n("Note:
"):i18n("Note:\n"); + text+=rtExpand(getNote(), richText); + text+=ps; + } + + return text; +} + +TQDateTime PilotDateEntry::dtStart() const +{ + FUNCTIONSETUP; + return readTm( getEventStart() ); +} + +TQDateTime PilotDateEntry::dtEnd() const +{ + FUNCTIONSETUP; + return readTm( getEventEnd() ); +} + +TQDateTime PilotDateEntry::dtRepeatEnd() const +{ + FUNCTIONSETUP; + return readTm( getRepeatEnd() ); +} + +unsigned int PilotDateEntry::alarmLeadTime() const +{ + FUNCTIONSETUP; + if (!isAlarmEnabled()) return 0; + + int adv = getAdvance(); + if ( adv < 0 ) + { + return 0; // Not possible to enter on the pilot + } + unsigned int t = adv; + int u = getAdvanceUnits(); + + + switch(u) + { + case advMinutes : t *= 60; break; + case advHours : t *= 3600; break; + case advDays : t *= 3600 * 24; break; + default: t = 0; + } + + return t; +} + +PilotRecord *PilotDateEntry::pack() const +{ + int i; + + pi_buffer_t *b = pi_buffer_new( sizeof(fAppointmentInfo) ); + i = pack_Appointment(const_cast(&fAppointmentInfo), b, datebook_v1); + if (i<0) + { + // Generic error from the pack_*() functions. + return 0; + } + + // pack_Appointment sets b->used + return new PilotRecord( b, this ); +} + +/* setExceptions sets a new set of exceptions. Note that + PilotDateEntry assumes ownership of the array and will + delete the old one. */ +void PilotDateEntry::setExceptions(struct tm *e) { + if (fAppointmentInfo.exception != e) + { + KPILOT_FREE(fAppointmentInfo.exception); + } + fAppointmentInfo.exception=e; +} + + +void PilotDateEntry::setDescriptionP(const char *desc, int l) +{ + FUNCTIONSETUP; + KPILOT_FREE(fAppointmentInfo.description); + + if (desc && *desc) + { + if (-1 == l) l=::strlen(desc); + fAppointmentInfo.description = + (char *) ::malloc(l + 1); + if (fAppointmentInfo.description) + { + strlcpy(fAppointmentInfo.description, desc, l+1); + } + else + { + WARNINGKPILOT << "malloc() failed, description not set" << endl; + } + } + else + { + fAppointmentInfo.description = 0L; + } +} + +void PilotDateEntry::setNoteP(const char *note, int l) +{ + FUNCTIONSETUP; + KPILOT_FREE(fAppointmentInfo.note); + + if (note && *note) + { + if (-1 == l) l=::strlen(note); + fAppointmentInfo.note = (char *)::malloc(l + 1); + if (fAppointmentInfo.note) + { + strlcpy(fAppointmentInfo.note, note,l+1); + } + else + { + WARNINGKPILOT << "malloc() failed, note not set" << endl; + } + } + else + { + fAppointmentInfo.note = 0L; + } +} + +void PilotDateEntry::setNote(const TQString &s) +{ + TQCString t = Pilot::toPilot(s); + setNoteP( t.data(),t.length() ); +} + +void PilotDateEntry::setLocation(const TQString &s) +{ + TQString note = Pilot::fromPilot(getNoteP()); + TQRegExp rxp = TQRegExp("^[Ll]ocation:[^\n]+\n"); + + // per TQString docs, this covers null and 0 length + if( s.isEmpty() ) + { + note.replace(rxp,""); + } + else + { + TQString location = "Location: " + s + "\n"; + int pos = note.find(rxp); + + if(pos >= 0) + { + note.replace( rxp, location ); + } + else + { + note = location + note; + setNote( note ); + } + } +} + +TQString PilotDateEntry::getLocation() const +{ + // Read the complete note here and not the filtered + // one from PilotDateEntry::getNote(); + TQString note = Pilot::fromPilot(getNoteP()); + TQRegExp rxp = TQRegExp("^[Ll]ocation:[^\n]+\n"); + int pos = note.find(rxp, 0); + + if(pos >= 0) + { + TQString location = rxp.capturedTexts().first(); + rxp = TQRegExp("^[Ll]ocation:[\\s|\t]*"); + location.replace(rxp,""); + location.replace("\n", ""); + return location; + } + else + { + return ""; + } +} + +void PilotDateEntry::setDescription(const TQString &s) +{ + TQCString t = Pilot::toPilot(s); + setDescriptionP( t.data(),t.length() ); +} + +TQString PilotDateEntry::getNote() const +{ + TQString note = Pilot::fromPilot(getNoteP()); + TQRegExp rxp = TQRegExp("^[Ll]ocation:[^\n]+\n"); + note.replace(rxp, "" ); + return note; +} + +TQString PilotDateEntry::getDescription() const +{ + return Pilot::fromPilot(getDescriptionP()); +} + diff --git a/lib/pilotDateEntry.h b/lib/pilotDateEntry.h index 4d33693..d960a22 100644 --- a/lib/pilotDateEntry.h +++ b/lib/pilotDateEntry.h @@ -5,7 +5,7 @@ ** Copyright (C) 1998-2001 by Dan Pilone ** Copyright (C) 2003-2004 Reinhold Kainhofer ** -** See the .cc file for an explanation of what this file is for. +** See the .cpp file for an explanation of what this file is for. */ /** @file pilotDateEntry.h defines a wrapper for datebook entries. */ diff --git a/lib/pilotLocalDatabase.cc b/lib/pilotLocalDatabase.cc deleted file mode 100644 index ea78ac0..0000000 --- a/lib/pilotLocalDatabase.cc +++ /dev/null @@ -1,762 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** -** This defines an interface to Pilot databases on the local disk. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 -#include -#include - -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "pilotRecord.h" -#include "pilotLocalDatabase.h" - -typedef TQValueVector Records; - -class PilotLocalDatabase::Private : public Records -{ -public: - static const int DEFAULT_SIZE = 128; - Private(int size=DEFAULT_SIZE) : Records(size) { resetIndex(); } - ~Private() { deleteRecords(); } - - void deleteRecords() - { - for (unsigned int i=0; iisEmpty()) - { - fPathName = *fPathBase; - } - else - { - fPathName = TDEGlobal::dirs()->saveLocation("data", - CSL1("kpilot/DBBackup/")); - } - fixupDBName(); - openDatabase(); - if (!isOpen()) - { - fPathName=path; - } - } - -} - -PilotLocalDatabase::PilotLocalDatabase(const TQString &dbName) : - PilotDatabase( TQString() ), - fPathName( TQString() ), - fDBName( TQString() ), - fAppInfo(0L), - fAppLen(0), - d(0L) -{ - FUNCTIONSETUP; - - int p = dbName.findRev( '/' ); - if (p<0) - { - // No slash - fPathName = CSL1("."); - fDBName = dbName; - } - else - { - fPathName = dbName.left(p); - fDBName = dbName.mid(p+1); - } - openDatabase(); -} - -PilotLocalDatabase::~PilotLocalDatabase() -{ - FUNCTIONSETUP; - - closeDatabase(); - delete[]fAppInfo; - delete d; -} - -// Changes any forward slashes to underscores -void PilotLocalDatabase::fixupDBName() -{ - FUNCTIONSETUP; - fDBName = fDBName.replace(CSL1("/"),CSL1("_")); -} - -bool PilotLocalDatabase::createDatabase(long creator, long type, int, int flags, int version) -{ - FUNCTIONSETUP; - - // if the database is already open, we cannot create it again. - // How about completely resetting it? (i.e. deleting it and then - // creating it again) - if (isOpen()) - { - DEBUGKPILOT << fname << ": Database " << fDBName - << " already open. Cannot recreate it." << endl; - return true; - } - - DEBUGKPILOT << fname << ": Creating database " << fDBName << endl; - - // Database names seem to be latin1. - Pilot::toPilot(fDBName, fDBInfo.name, sizeof(fDBInfo.name)); - fDBInfo.creator=creator; - fDBInfo.type=type; - fDBInfo.more=0; - fDBInfo.flags=flags; - fDBInfo.miscFlags=0; - fDBInfo.version=version; - fDBInfo.modnum=0; - fDBInfo.index=0; - fDBInfo.createDate=(TQDateTime::currentDateTime()).toTime_t(); - fDBInfo.modifyDate=(TQDateTime::currentDateTime()).toTime_t(); - fDBInfo.backupDate=(TQDateTime::currentDateTime()).toTime_t(); - - delete[] fAppInfo; - fAppInfo=0L; - fAppLen=0; - - d = new Private; - - // TODO: Do I have to open it explicitly??? - setDBOpen(true); - return true; -} - -int PilotLocalDatabase::deleteDatabase() -{ - FUNCTIONSETUP; - if (isOpen()) - { - closeDatabase(); - } - - TQString dbpath=dbPathName(); - TQFile fl(dbpath); - if (TQFile::remove(dbPathName())) - { - return 0; - } - else - { - return -1; - } -} - - - -// Reads the application block info -int PilotLocalDatabase::readAppBlock(unsigned char *buffer, int size) -{ - FUNCTIONSETUP; - - size_t m = kMin((size_t)size,(size_t)fAppLen); - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - memset(buffer,0,m); - return -1; - } - - memcpy((void *) buffer, fAppInfo, m); - return fAppLen; -} - -int PilotLocalDatabase::writeAppBlock(unsigned char *buffer, int len) -{ - FUNCTIONSETUP; - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - return -1; - } - delete[]fAppInfo; - fAppLen = len; - fAppInfo = new char[fAppLen]; - - memcpy(fAppInfo, (void *) buffer, fAppLen); - return 0; -} - - -// returns the number of records in the database -unsigned int PilotLocalDatabase::recordCount() const -{ - if (d && isOpen()) - { - return d->size(); - } - else - { - return 0; - } -} - - -// Returns a TQValueList of all record ids in the database. -TQValueList PilotLocalDatabase::idList() -{ - int idlen=recordCount(); - TQValueList idlist; - if (idlen<=0) - { - return idlist; - } - - // now create the TQValue list from the idarr: - for (int i=0; iid()); - } - - return idlist; -} - -// Reads a record from database by id, returns record length -PilotRecord *PilotLocalDatabase::readRecordById(recordid_t id) -{ - FUNCTIONSETUP; - - if (!isOpen()) - { - WARNINGKPILOT << "Database '" << fDBName << " not open!" << endl; - return 0L; - } - - d->pending = -1; - - for (unsigned int i = 0; i < d->size(); i++) - { - if ((*d)[i]->id() == id) - { - PilotRecord *newRecord = new PilotRecord((*d)[i]); - d->current = i; - return newRecord; - } - } - return 0L; -} - -// Reads a record from database, returns the record -PilotRecord *PilotLocalDatabase::readRecordByIndex(int index) -{ - FUNCTIONSETUP; - - if (index < 0) - { - DEBUGKPILOT << fname << ": Index " << index << " is bogus." << endl; - return 0L; - } - - d->pending = -1; - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - return 0L; - } - - DEBUGKPILOT << fname << ": Index=" << index << " Count=" << recordCount() << endl; - - if ( (unsigned int)index >= recordCount() ) - { - return 0L; - } - PilotRecord *newRecord = new PilotRecord((*d)[index]); - d->current = index; - - return newRecord; -} - -// Reads the next record from database in category 'category' -PilotRecord *PilotLocalDatabase::readNextRecInCategory(int category) -{ - FUNCTIONSETUP; - d->pending = -1; - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - return 0L; - } - - while ((d->current < d->size()) - && ((*d)[d->current]->category() != category)) - { - d->current++; - } - - if (d->current >= d->size()) - return 0L; - PilotRecord *newRecord = new PilotRecord((*d)[d->current]); - - d->current++; // so we skip it next time - return newRecord; -} - -const PilotRecord *PilotLocalDatabase::findNextNewRecord() -{ - FUNCTIONSETUP; - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - return 0L; - } - DEBUGKPILOT << fname << ": looking for new record from " << d->current << endl; - // Should this also check for deleted? - while ((d->current < d->size()) - && ((*d)[d->current]->id() != 0 )) - { - d->current++; - } - - if (d->current >= d->size()) - return 0L; - - d->pending = d->current; // Record which one needs the new id - d->current++; // so we skip it next time - return (*d)[d->pending]; -} - -PilotRecord *PilotLocalDatabase::readNextModifiedRec(int *ind) -{ - FUNCTIONSETUP; - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - return 0L; - } - - d->pending = -1; - // Should this also check for deleted? - while ((d->current < d->size()) - && !((*d)[d->current]->isModified()) && ((*d)[d->current]->id()>0 )) - { - d->current++; - } - - if (d->current >= d->size()) - { - return 0L; - } - PilotRecord *newRecord = new PilotRecord((*d)[d->current]); - if (ind) - { - *ind=d->current; - } - - d->pending = d->current; // Record which one needs the new id - d->current++; // so we skip it next time - return newRecord; -} - -// Writes a new ID to the record specified the index. Not supported on Serial connections -recordid_t PilotLocalDatabase::updateID(recordid_t id) -{ - FUNCTIONSETUP; - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - return 0; - } - if (d->pending < 0) - { - WARNINGKPILOT << "Last call was NOT readNextModifiedRec()" << endl; - return 0; - } - (*d)[d->pending]->setID(id); - d->pending = -1; - return id; -} - -// Writes a new record to database (if 'id' == 0, it is assumed that this is a new record to be installed on pilot) -recordid_t PilotLocalDatabase::writeRecord(PilotRecord * newRecord) -{ - FUNCTIONSETUP; - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - return 0; - } - - d->pending = -1; - if (!newRecord) - { - WARNINGKPILOT << "Record to be written is invalid!" << endl; - return 0; - } - - // Instead of making the app do it, assume that whenever a record is - // written to the database it is dirty. (You can clean up the database with - // resetSyncFlags().) This will make things get copied twice during a hot-sync - // but shouldn't cause any other major headaches. - newRecord->setModified( true ); - - // First check to see if we have this record: - if (newRecord->id() != 0) - { - for (unsigned int i = 0; i < d->size(); i++) - if ((*d)[i]->id() == newRecord->id()) - { - delete (*d)[i]; - - (*d)[i] = new PilotRecord(newRecord); - return 0; - } - } - // Ok, we don't have it, so just tack it on. - d->append( new PilotRecord(newRecord) ); - return newRecord->id(); -} - -// Deletes a record with the given recordid_t from the database, or all records, if all is set to true. The recordid_t will be ignored in this case -int PilotLocalDatabase::deleteRecord(recordid_t id, bool all) -{ - FUNCTIONSETUP; - if (!isOpen()) - { - WARNINGKPILOT <<"DB not open"<resetIndex(); - if (all) - { - d->deleteRecords(); - d->clear(); - return 0; - } - else - { - Private::Iterator i; - for ( i=d->begin() ; i!=d->end(); ++i) - { - if ((*i) && (*i)->id() == id) break; - } - if ( (i!=d->end()) && (*i) && (*i)->id() == id) - { - d->erase(i); - } - else - { - // Record with this id does not exist! - return -1; - } - } - return 0; -} - - -// Resets all records in the database to not dirty. -int PilotLocalDatabase::resetSyncFlags() -{ - FUNCTIONSETUP; - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - return -1; - } - d->pending = -1; - for (unsigned int i = 0; i < d->size(); i++) - { - (*d)[i]->setModified( false ); - } - return 0; -} - -// Resets next record index to beginning -int PilotLocalDatabase::resetDBIndex() -{ - FUNCTIONSETUP; - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - return -1; - } - d->resetIndex(); - return 0; -} - -// Purges all Archived/Deleted records from Palm Pilot database -int PilotLocalDatabase::cleanup() -{ - FUNCTIONSETUP; - if (!isOpen()) - { - WARNINGKPILOT << "DB not open!" << endl; - return -1; - } - d->resetIndex(); - - /* Not the for loop one might expect since when we erase() - * a record the iterator changes too. - */ - Private::Iterator i = d->begin(); - while ( i!=d->end() ) - { - if ( (*i)->isDeleted() || (*i)->isArchived() ) - { - delete (*i); - i = d->erase(i); - } - else - { - ++i; - } - } - - // Don't have to do anything. Will be taken care of by closeDatabase()... - // Changed! - return 0; -} - -TQString PilotLocalDatabase::dbPathName() const -{ - FUNCTIONSETUP; - TQString tempName(fPathName); - TQString slash = CSL1("/"); - - if (!tempName.endsWith(slash)) tempName += slash; - tempName += getDBName(); - tempName += CSL1(".pdb"); - return tempName; -} - -void PilotLocalDatabase::openDatabase() -{ - FUNCTIONSETUP; - - pi_file *dbFile; - - setDBOpen(false); - - dbFile = pi_file_open( TQFile::encodeName(dbPathName()) ); - if (dbFile == 0L) - { - TQString path = dbPathName(); - DEBUGKPILOT << fname << ": Failed to open " << path << endl; - return; - } - - - PI_SIZE_T size = 0; - void *tmpBuffer; - pi_file_get_info(dbFile, &fDBInfo); - pi_file_get_app_info(dbFile, &tmpBuffer, &size); - fAppLen = size; - fAppInfo = new char[fAppLen]; - memcpy(fAppInfo, tmpBuffer, fAppLen); - - int count; - pi_file_get_entries(dbFile, &count); - if (count >= 0) - { - KPILOT_DELETE(d); - d = new Private(count); - } - - int attr, cat; - recordid_t id; - unsigned int i = 0; - while (pi_file_read_record(dbFile, i, - &tmpBuffer, &size, &attr, &cat, &id) == 0) - { - pi_buffer_t *b = pi_buffer_new(size); - memcpy(b->data,tmpBuffer,size); - b->used = size; - (*d)[i] = new PilotRecord(b, attr, cat, id); - i++; - } - pi_file_close(dbFile); // We done with it once we've read it in. - - KSaveFile::backupFile( dbPathName() ); - - setDBOpen(true); -} - -void PilotLocalDatabase::closeDatabase() -{ - FUNCTIONSETUP; - pi_file *dbFile; - - if (!isOpen()) - { - DEBUGKPILOT << fname << ": Database " << fDBName - << " is not open. Cannot close and write it" - << endl; - return; - } - - TQString newName = dbPathName() + CSL1(".new"); - TQString path = dbPathName(); - DEBUGKPILOT << fname - << ": Creating temp file " << newName - << " for the database file " << path << endl; - - dbFile = pi_file_create(TQFile::encodeName(newName),&fDBInfo); - pi_file_set_app_info(dbFile, fAppInfo, fAppLen); - - for (unsigned int i = 0; i < d->size(); i++) - { - // How did a NULL pointer sneak in here? - if (!(*d)[i]) - { - continue; - } - - if (((*d)[i]->id() == 0) && ((*d)[i]->isDeleted())) - { - // Just ignore it - } - else - { - pi_file_append_record(dbFile, - (*d)[i]->data(), - (*d)[i]->size(), - (*d)[i]->attributes(), (*d)[i]->category(), - (*d)[i]->id()); - } - } - - pi_file_close(dbFile); - TQFile::remove(dbPathName()); - rename((const char *) TQFile::encodeName(newName), - (const char *) TQFile::encodeName(dbPathName())); - setDBOpen(false); -} - - -TQString *PilotLocalDatabase::fPathBase = 0L; - -void PilotLocalDatabase::setDBPath(const TQString &s) -{ - FUNCTIONSETUP; - - DEBUGKPILOT << fname - << ": Setting default DB path to " - << s - << endl; - - if (!fPathBase) - { - fPathBase = new TQString(s); - } - else - { - *fPathBase = s; - } -} - -/* virtual */ PilotDatabase::DBType PilotLocalDatabase::dbType() const -{ - return eLocalDB; -} - - -/* static */ bool PilotLocalDatabase::infoFromFile( const TQString &path, DBInfo *d ) -{ - FUNCTIONSETUP; - - pi_file *f = 0L; - - if (!d) - { - return false; - } - if (!TQFile::exists(path)) - { - return false; - } - - TQCString fileName = TQFile::encodeName( path ); - f = pi_file_open( fileName ); - if (!f) - { - WARNINGKPILOT << "Can't open " << path << endl; - return false; - } - - pi_file_get_info(f,d); - pi_file_close(f); - - return true; -} - diff --git a/lib/pilotLocalDatabase.cpp b/lib/pilotLocalDatabase.cpp new file mode 100644 index 0000000..ea78ac0 --- /dev/null +++ b/lib/pilotLocalDatabase.cpp @@ -0,0 +1,762 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** +** This defines an interface to Pilot databases on the local disk. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "pilotRecord.h" +#include "pilotLocalDatabase.h" + +typedef TQValueVector Records; + +class PilotLocalDatabase::Private : public Records +{ +public: + static const int DEFAULT_SIZE = 128; + Private(int size=DEFAULT_SIZE) : Records(size) { resetIndex(); } + ~Private() { deleteRecords(); } + + void deleteRecords() + { + for (unsigned int i=0; iisEmpty()) + { + fPathName = *fPathBase; + } + else + { + fPathName = TDEGlobal::dirs()->saveLocation("data", + CSL1("kpilot/DBBackup/")); + } + fixupDBName(); + openDatabase(); + if (!isOpen()) + { + fPathName=path; + } + } + +} + +PilotLocalDatabase::PilotLocalDatabase(const TQString &dbName) : + PilotDatabase( TQString() ), + fPathName( TQString() ), + fDBName( TQString() ), + fAppInfo(0L), + fAppLen(0), + d(0L) +{ + FUNCTIONSETUP; + + int p = dbName.findRev( '/' ); + if (p<0) + { + // No slash + fPathName = CSL1("."); + fDBName = dbName; + } + else + { + fPathName = dbName.left(p); + fDBName = dbName.mid(p+1); + } + openDatabase(); +} + +PilotLocalDatabase::~PilotLocalDatabase() +{ + FUNCTIONSETUP; + + closeDatabase(); + delete[]fAppInfo; + delete d; +} + +// Changes any forward slashes to underscores +void PilotLocalDatabase::fixupDBName() +{ + FUNCTIONSETUP; + fDBName = fDBName.replace(CSL1("/"),CSL1("_")); +} + +bool PilotLocalDatabase::createDatabase(long creator, long type, int, int flags, int version) +{ + FUNCTIONSETUP; + + // if the database is already open, we cannot create it again. + // How about completely resetting it? (i.e. deleting it and then + // creating it again) + if (isOpen()) + { + DEBUGKPILOT << fname << ": Database " << fDBName + << " already open. Cannot recreate it." << endl; + return true; + } + + DEBUGKPILOT << fname << ": Creating database " << fDBName << endl; + + // Database names seem to be latin1. + Pilot::toPilot(fDBName, fDBInfo.name, sizeof(fDBInfo.name)); + fDBInfo.creator=creator; + fDBInfo.type=type; + fDBInfo.more=0; + fDBInfo.flags=flags; + fDBInfo.miscFlags=0; + fDBInfo.version=version; + fDBInfo.modnum=0; + fDBInfo.index=0; + fDBInfo.createDate=(TQDateTime::currentDateTime()).toTime_t(); + fDBInfo.modifyDate=(TQDateTime::currentDateTime()).toTime_t(); + fDBInfo.backupDate=(TQDateTime::currentDateTime()).toTime_t(); + + delete[] fAppInfo; + fAppInfo=0L; + fAppLen=0; + + d = new Private; + + // TODO: Do I have to open it explicitly??? + setDBOpen(true); + return true; +} + +int PilotLocalDatabase::deleteDatabase() +{ + FUNCTIONSETUP; + if (isOpen()) + { + closeDatabase(); + } + + TQString dbpath=dbPathName(); + TQFile fl(dbpath); + if (TQFile::remove(dbPathName())) + { + return 0; + } + else + { + return -1; + } +} + + + +// Reads the application block info +int PilotLocalDatabase::readAppBlock(unsigned char *buffer, int size) +{ + FUNCTIONSETUP; + + size_t m = kMin((size_t)size,(size_t)fAppLen); + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + memset(buffer,0,m); + return -1; + } + + memcpy((void *) buffer, fAppInfo, m); + return fAppLen; +} + +int PilotLocalDatabase::writeAppBlock(unsigned char *buffer, int len) +{ + FUNCTIONSETUP; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + return -1; + } + delete[]fAppInfo; + fAppLen = len; + fAppInfo = new char[fAppLen]; + + memcpy(fAppInfo, (void *) buffer, fAppLen); + return 0; +} + + +// returns the number of records in the database +unsigned int PilotLocalDatabase::recordCount() const +{ + if (d && isOpen()) + { + return d->size(); + } + else + { + return 0; + } +} + + +// Returns a TQValueList of all record ids in the database. +TQValueList PilotLocalDatabase::idList() +{ + int idlen=recordCount(); + TQValueList idlist; + if (idlen<=0) + { + return idlist; + } + + // now create the TQValue list from the idarr: + for (int i=0; iid()); + } + + return idlist; +} + +// Reads a record from database by id, returns record length +PilotRecord *PilotLocalDatabase::readRecordById(recordid_t id) +{ + FUNCTIONSETUP; + + if (!isOpen()) + { + WARNINGKPILOT << "Database '" << fDBName << " not open!" << endl; + return 0L; + } + + d->pending = -1; + + for (unsigned int i = 0; i < d->size(); i++) + { + if ((*d)[i]->id() == id) + { + PilotRecord *newRecord = new PilotRecord((*d)[i]); + d->current = i; + return newRecord; + } + } + return 0L; +} + +// Reads a record from database, returns the record +PilotRecord *PilotLocalDatabase::readRecordByIndex(int index) +{ + FUNCTIONSETUP; + + if (index < 0) + { + DEBUGKPILOT << fname << ": Index " << index << " is bogus." << endl; + return 0L; + } + + d->pending = -1; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + return 0L; + } + + DEBUGKPILOT << fname << ": Index=" << index << " Count=" << recordCount() << endl; + + if ( (unsigned int)index >= recordCount() ) + { + return 0L; + } + PilotRecord *newRecord = new PilotRecord((*d)[index]); + d->current = index; + + return newRecord; +} + +// Reads the next record from database in category 'category' +PilotRecord *PilotLocalDatabase::readNextRecInCategory(int category) +{ + FUNCTIONSETUP; + d->pending = -1; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + return 0L; + } + + while ((d->current < d->size()) + && ((*d)[d->current]->category() != category)) + { + d->current++; + } + + if (d->current >= d->size()) + return 0L; + PilotRecord *newRecord = new PilotRecord((*d)[d->current]); + + d->current++; // so we skip it next time + return newRecord; +} + +const PilotRecord *PilotLocalDatabase::findNextNewRecord() +{ + FUNCTIONSETUP; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + return 0L; + } + DEBUGKPILOT << fname << ": looking for new record from " << d->current << endl; + // Should this also check for deleted? + while ((d->current < d->size()) + && ((*d)[d->current]->id() != 0 )) + { + d->current++; + } + + if (d->current >= d->size()) + return 0L; + + d->pending = d->current; // Record which one needs the new id + d->current++; // so we skip it next time + return (*d)[d->pending]; +} + +PilotRecord *PilotLocalDatabase::readNextModifiedRec(int *ind) +{ + FUNCTIONSETUP; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + return 0L; + } + + d->pending = -1; + // Should this also check for deleted? + while ((d->current < d->size()) + && !((*d)[d->current]->isModified()) && ((*d)[d->current]->id()>0 )) + { + d->current++; + } + + if (d->current >= d->size()) + { + return 0L; + } + PilotRecord *newRecord = new PilotRecord((*d)[d->current]); + if (ind) + { + *ind=d->current; + } + + d->pending = d->current; // Record which one needs the new id + d->current++; // so we skip it next time + return newRecord; +} + +// Writes a new ID to the record specified the index. Not supported on Serial connections +recordid_t PilotLocalDatabase::updateID(recordid_t id) +{ + FUNCTIONSETUP; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + return 0; + } + if (d->pending < 0) + { + WARNINGKPILOT << "Last call was NOT readNextModifiedRec()" << endl; + return 0; + } + (*d)[d->pending]->setID(id); + d->pending = -1; + return id; +} + +// Writes a new record to database (if 'id' == 0, it is assumed that this is a new record to be installed on pilot) +recordid_t PilotLocalDatabase::writeRecord(PilotRecord * newRecord) +{ + FUNCTIONSETUP; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + return 0; + } + + d->pending = -1; + if (!newRecord) + { + WARNINGKPILOT << "Record to be written is invalid!" << endl; + return 0; + } + + // Instead of making the app do it, assume that whenever a record is + // written to the database it is dirty. (You can clean up the database with + // resetSyncFlags().) This will make things get copied twice during a hot-sync + // but shouldn't cause any other major headaches. + newRecord->setModified( true ); + + // First check to see if we have this record: + if (newRecord->id() != 0) + { + for (unsigned int i = 0; i < d->size(); i++) + if ((*d)[i]->id() == newRecord->id()) + { + delete (*d)[i]; + + (*d)[i] = new PilotRecord(newRecord); + return 0; + } + } + // Ok, we don't have it, so just tack it on. + d->append( new PilotRecord(newRecord) ); + return newRecord->id(); +} + +// Deletes a record with the given recordid_t from the database, or all records, if all is set to true. The recordid_t will be ignored in this case +int PilotLocalDatabase::deleteRecord(recordid_t id, bool all) +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT <<"DB not open"<resetIndex(); + if (all) + { + d->deleteRecords(); + d->clear(); + return 0; + } + else + { + Private::Iterator i; + for ( i=d->begin() ; i!=d->end(); ++i) + { + if ((*i) && (*i)->id() == id) break; + } + if ( (i!=d->end()) && (*i) && (*i)->id() == id) + { + d->erase(i); + } + else + { + // Record with this id does not exist! + return -1; + } + } + return 0; +} + + +// Resets all records in the database to not dirty. +int PilotLocalDatabase::resetSyncFlags() +{ + FUNCTIONSETUP; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + return -1; + } + d->pending = -1; + for (unsigned int i = 0; i < d->size(); i++) + { + (*d)[i]->setModified( false ); + } + return 0; +} + +// Resets next record index to beginning +int PilotLocalDatabase::resetDBIndex() +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + return -1; + } + d->resetIndex(); + return 0; +} + +// Purges all Archived/Deleted records from Palm Pilot database +int PilotLocalDatabase::cleanup() +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open!" << endl; + return -1; + } + d->resetIndex(); + + /* Not the for loop one might expect since when we erase() + * a record the iterator changes too. + */ + Private::Iterator i = d->begin(); + while ( i!=d->end() ) + { + if ( (*i)->isDeleted() || (*i)->isArchived() ) + { + delete (*i); + i = d->erase(i); + } + else + { + ++i; + } + } + + // Don't have to do anything. Will be taken care of by closeDatabase()... + // Changed! + return 0; +} + +TQString PilotLocalDatabase::dbPathName() const +{ + FUNCTIONSETUP; + TQString tempName(fPathName); + TQString slash = CSL1("/"); + + if (!tempName.endsWith(slash)) tempName += slash; + tempName += getDBName(); + tempName += CSL1(".pdb"); + return tempName; +} + +void PilotLocalDatabase::openDatabase() +{ + FUNCTIONSETUP; + + pi_file *dbFile; + + setDBOpen(false); + + dbFile = pi_file_open( TQFile::encodeName(dbPathName()) ); + if (dbFile == 0L) + { + TQString path = dbPathName(); + DEBUGKPILOT << fname << ": Failed to open " << path << endl; + return; + } + + + PI_SIZE_T size = 0; + void *tmpBuffer; + pi_file_get_info(dbFile, &fDBInfo); + pi_file_get_app_info(dbFile, &tmpBuffer, &size); + fAppLen = size; + fAppInfo = new char[fAppLen]; + memcpy(fAppInfo, tmpBuffer, fAppLen); + + int count; + pi_file_get_entries(dbFile, &count); + if (count >= 0) + { + KPILOT_DELETE(d); + d = new Private(count); + } + + int attr, cat; + recordid_t id; + unsigned int i = 0; + while (pi_file_read_record(dbFile, i, + &tmpBuffer, &size, &attr, &cat, &id) == 0) + { + pi_buffer_t *b = pi_buffer_new(size); + memcpy(b->data,tmpBuffer,size); + b->used = size; + (*d)[i] = new PilotRecord(b, attr, cat, id); + i++; + } + pi_file_close(dbFile); // We done with it once we've read it in. + + KSaveFile::backupFile( dbPathName() ); + + setDBOpen(true); +} + +void PilotLocalDatabase::closeDatabase() +{ + FUNCTIONSETUP; + pi_file *dbFile; + + if (!isOpen()) + { + DEBUGKPILOT << fname << ": Database " << fDBName + << " is not open. Cannot close and write it" + << endl; + return; + } + + TQString newName = dbPathName() + CSL1(".new"); + TQString path = dbPathName(); + DEBUGKPILOT << fname + << ": Creating temp file " << newName + << " for the database file " << path << endl; + + dbFile = pi_file_create(TQFile::encodeName(newName),&fDBInfo); + pi_file_set_app_info(dbFile, fAppInfo, fAppLen); + + for (unsigned int i = 0; i < d->size(); i++) + { + // How did a NULL pointer sneak in here? + if (!(*d)[i]) + { + continue; + } + + if (((*d)[i]->id() == 0) && ((*d)[i]->isDeleted())) + { + // Just ignore it + } + else + { + pi_file_append_record(dbFile, + (*d)[i]->data(), + (*d)[i]->size(), + (*d)[i]->attributes(), (*d)[i]->category(), + (*d)[i]->id()); + } + } + + pi_file_close(dbFile); + TQFile::remove(dbPathName()); + rename((const char *) TQFile::encodeName(newName), + (const char *) TQFile::encodeName(dbPathName())); + setDBOpen(false); +} + + +TQString *PilotLocalDatabase::fPathBase = 0L; + +void PilotLocalDatabase::setDBPath(const TQString &s) +{ + FUNCTIONSETUP; + + DEBUGKPILOT << fname + << ": Setting default DB path to " + << s + << endl; + + if (!fPathBase) + { + fPathBase = new TQString(s); + } + else + { + *fPathBase = s; + } +} + +/* virtual */ PilotDatabase::DBType PilotLocalDatabase::dbType() const +{ + return eLocalDB; +} + + +/* static */ bool PilotLocalDatabase::infoFromFile( const TQString &path, DBInfo *d ) +{ + FUNCTIONSETUP; + + pi_file *f = 0L; + + if (!d) + { + return false; + } + if (!TQFile::exists(path)) + { + return false; + } + + TQCString fileName = TQFile::encodeName( path ); + f = pi_file_open( fileName ); + if (!f) + { + WARNINGKPILOT << "Can't open " << path << endl; + return false; + } + + pi_file_get_info(f,d); + pi_file_close(f); + + return true; +} + diff --git a/lib/pilotMemo.cc b/lib/pilotMemo.cc deleted file mode 100644 index c163e46..0000000 --- a/lib/pilotMemo.cc +++ /dev/null @@ -1,135 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** -** This is a C++ wrapper for the Pilot's Memo Pad structures. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 - -#include "pilotMemo.h" -#include "pilotDatabase.h" - - - -PilotMemo::PilotMemo(const PilotRecord * rec) : PilotRecordBase(rec) -{ - FUNCTIONSETUP; - fText = Pilot::fromPilot((const char *)(rec->data()),rec->size()); -} - -PilotRecord *PilotMemo::pack() -{ - FUNCTIONSETUPL(4); - int i; - - int len = fText.length() + 8; - struct Memo buf; - buf.text = new char[len]; - - // put our text into buf - i = Pilot::toPilot(fText, buf.text, len); - - pi_buffer_t *b = pi_buffer_new(len); - i = pack_Memo(&buf, b, memo_v1); - - DEBUGKPILOT << fname << ": original text: [" << fText - << "], buf.text: [" << buf.text - << "], b->data: [" << b->data << "]" << endl; - - if (i<0) - { - // Generic error from the pack_*() functions. - delete[] buf.text; - return 0; - } - - // pack_Appointment sets b->used - PilotRecord *r = new PilotRecord(b, this); - delete[] buf.text; - return r; -} - - -TQString PilotMemo::getTextRepresentation(TQt::TextFormat richText) -{ - if (richText==TQt::RichText) - { - return i18n("Title: %1
\nMemoText:
%2"). - arg(rtExpand(getTitle(), richText)).arg(rtExpand(text(), richText)); - } - else - { - return i18n("Title: %1\nMemoText:\n%2").arg(getTitle()).arg(text()); - } -} - - -TQString PilotMemo::getTitle() const -{ - if (fText.isEmpty()) return TQString(); - - int memoTitleLen = fText.find('\n'); - if (-1 == memoTitleLen) memoTitleLen=fText.length(); - return fText.left(memoTitleLen); -} - -TQString PilotMemo::shortTitle() const -{ - FUNCTIONSETUP; - TQString t = TQString(getTitle()).simplifyWhiteSpace(); - - if (t.length() < 32) - return t; - t.truncate(40); - - int spaceIndex = t.findRev(' '); - - if (spaceIndex > 32) - { - t.truncate(spaceIndex); - } - - t += CSL1("..."); - - return t; -} - -TQString PilotMemo::sensibleTitle() const -{ - FUNCTIONSETUP; - TQString s = getTitle(); - - if (!s.isEmpty()) - { - return s; - } - else - { - return i18n("[unknown]"); - } -} - diff --git a/lib/pilotMemo.cpp b/lib/pilotMemo.cpp new file mode 100644 index 0000000..c163e46 --- /dev/null +++ b/lib/pilotMemo.cpp @@ -0,0 +1,135 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** +** This is a C++ wrapper for the Pilot's Memo Pad structures. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 + +#include "pilotMemo.h" +#include "pilotDatabase.h" + + + +PilotMemo::PilotMemo(const PilotRecord * rec) : PilotRecordBase(rec) +{ + FUNCTIONSETUP; + fText = Pilot::fromPilot((const char *)(rec->data()),rec->size()); +} + +PilotRecord *PilotMemo::pack() +{ + FUNCTIONSETUPL(4); + int i; + + int len = fText.length() + 8; + struct Memo buf; + buf.text = new char[len]; + + // put our text into buf + i = Pilot::toPilot(fText, buf.text, len); + + pi_buffer_t *b = pi_buffer_new(len); + i = pack_Memo(&buf, b, memo_v1); + + DEBUGKPILOT << fname << ": original text: [" << fText + << "], buf.text: [" << buf.text + << "], b->data: [" << b->data << "]" << endl; + + if (i<0) + { + // Generic error from the pack_*() functions. + delete[] buf.text; + return 0; + } + + // pack_Appointment sets b->used + PilotRecord *r = new PilotRecord(b, this); + delete[] buf.text; + return r; +} + + +TQString PilotMemo::getTextRepresentation(TQt::TextFormat richText) +{ + if (richText==TQt::RichText) + { + return i18n("Title: %1
\nMemoText:
%2"). + arg(rtExpand(getTitle(), richText)).arg(rtExpand(text(), richText)); + } + else + { + return i18n("Title: %1\nMemoText:\n%2").arg(getTitle()).arg(text()); + } +} + + +TQString PilotMemo::getTitle() const +{ + if (fText.isEmpty()) return TQString(); + + int memoTitleLen = fText.find('\n'); + if (-1 == memoTitleLen) memoTitleLen=fText.length(); + return fText.left(memoTitleLen); +} + +TQString PilotMemo::shortTitle() const +{ + FUNCTIONSETUP; + TQString t = TQString(getTitle()).simplifyWhiteSpace(); + + if (t.length() < 32) + return t; + t.truncate(40); + + int spaceIndex = t.findRev(' '); + + if (spaceIndex > 32) + { + t.truncate(spaceIndex); + } + + t += CSL1("..."); + + return t; +} + +TQString PilotMemo::sensibleTitle() const +{ + FUNCTIONSETUP; + TQString s = getTitle(); + + if (!s.isEmpty()) + { + return s; + } + else + { + return i18n("[unknown]"); + } +} + diff --git a/lib/pilotMemo.h b/lib/pilotMemo.h index cc5389d..b8328f5 100644 --- a/lib/pilotMemo.h +++ b/lib/pilotMemo.h @@ -4,7 +4,7 @@ ** ** Copyright (C) 1998-2001 by Dan Pilone ** -** See the .cc file for an explanation of what this file is for. +** See the .cpp file for an explanation of what this file is for. */ /* diff --git a/lib/pilotRecord.cc b/lib/pilotRecord.cc deleted file mode 100644 index 8d5940a..0000000 --- a/lib/pilotRecord.cc +++ /dev/null @@ -1,132 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** -** This is a wrapper for pilot-link's general -** Pilot database structures. These records are -*** just collections of bits. See PilotAppCategory -** for interpreting the bits in a meaningful way. -** -** As a crufty hack, the non-inline parts of -** PilotAppCategory live in this file as well. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 - -#include - -#include -#include - -#include "pilot.h" -#include "pilotRecord.h" - - - -/* virtual */ TQString PilotRecordBase::textRepresentation() const -{ - return CSL1("[ %1,%2,%3 ]") . arg(attributes(),category(),id()); -} - -/* virtual */ TQString PilotRecord::textRepresentation() const -{ - return CSL1("[ %1,%2 ]") - .arg(PilotRecordBase::textRepresentation()) - .arg(size()); -} - - - -/* static */ int PilotRecord::fAllocated = 0; -/* static */ int PilotRecord::fDeleted = 0; - -/* static */ void PilotRecord::allocationInfo() -{ - FUNCTIONSETUP; - DEBUGKPILOT << fname - << ": Allocated " << fAllocated - << " Deleted " << fDeleted << endl; -} - -PilotRecord::PilotRecord(void *data, int len, int attrib, int cat, recordid_t uid) : - PilotRecordBase(attrib,cat,uid), - fData(0L), - fLen(len), - fBuffer(0L) -{ - FUNCTIONSETUPL(4); - fData = new char[len]; - - memcpy(fData, data, len); - - fAllocated++; -} - -PilotRecord::PilotRecord(PilotRecord * orig) : - PilotRecordBase( orig->attributes(), orig->category(), orig->id() ) , - fBuffer(0L) -{ - FUNCTIONSETUPL(4); - fData = new char[orig->size()]; - - memcpy(fData, orig->data(), orig->size()); - fLen = orig->size(); - fAllocated++; -} - -PilotRecord & PilotRecord::operator = (PilotRecord & orig) -{ - FUNCTIONSETUP; - if (fBuffer) - { - pi_buffer_free(fBuffer); - fBuffer=0L; - fData=0L; - } - - if (fData) - delete[]fData; - fData = new char[orig.size()]; - - memcpy(fData, orig.data(), orig.size()); - fLen = orig.size(); - setAttributes( orig.attributes() ); - setCategory( orig.category() ); - setID( orig.id() ); - return *this; -} - -void PilotRecord::setData(const char *data, int len) -{ - FUNCTIONSETUP; - if (fData) - delete[]fData; - fData = new char[len]; - - memcpy(fData, data, len); - fLen = len; -} - diff --git a/lib/pilotRecord.cpp b/lib/pilotRecord.cpp new file mode 100644 index 0000000..8d5940a --- /dev/null +++ b/lib/pilotRecord.cpp @@ -0,0 +1,132 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** +** This is a wrapper for pilot-link's general +** Pilot database structures. These records are +*** just collections of bits. See PilotAppCategory +** for interpreting the bits in a meaningful way. +** +** As a crufty hack, the non-inline parts of +** PilotAppCategory live in this file as well. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 + +#include + +#include +#include + +#include "pilot.h" +#include "pilotRecord.h" + + + +/* virtual */ TQString PilotRecordBase::textRepresentation() const +{ + return CSL1("[ %1,%2,%3 ]") . arg(attributes(),category(),id()); +} + +/* virtual */ TQString PilotRecord::textRepresentation() const +{ + return CSL1("[ %1,%2 ]") + .arg(PilotRecordBase::textRepresentation()) + .arg(size()); +} + + + +/* static */ int PilotRecord::fAllocated = 0; +/* static */ int PilotRecord::fDeleted = 0; + +/* static */ void PilotRecord::allocationInfo() +{ + FUNCTIONSETUP; + DEBUGKPILOT << fname + << ": Allocated " << fAllocated + << " Deleted " << fDeleted << endl; +} + +PilotRecord::PilotRecord(void *data, int len, int attrib, int cat, recordid_t uid) : + PilotRecordBase(attrib,cat,uid), + fData(0L), + fLen(len), + fBuffer(0L) +{ + FUNCTIONSETUPL(4); + fData = new char[len]; + + memcpy(fData, data, len); + + fAllocated++; +} + +PilotRecord::PilotRecord(PilotRecord * orig) : + PilotRecordBase( orig->attributes(), orig->category(), orig->id() ) , + fBuffer(0L) +{ + FUNCTIONSETUPL(4); + fData = new char[orig->size()]; + + memcpy(fData, orig->data(), orig->size()); + fLen = orig->size(); + fAllocated++; +} + +PilotRecord & PilotRecord::operator = (PilotRecord & orig) +{ + FUNCTIONSETUP; + if (fBuffer) + { + pi_buffer_free(fBuffer); + fBuffer=0L; + fData=0L; + } + + if (fData) + delete[]fData; + fData = new char[orig.size()]; + + memcpy(fData, orig.data(), orig.size()); + fLen = orig.size(); + setAttributes( orig.attributes() ); + setCategory( orig.category() ); + setID( orig.id() ); + return *this; +} + +void PilotRecord::setData(const char *data, int len) +{ + FUNCTIONSETUP; + if (fData) + delete[]fData; + fData = new char[len]; + + memcpy(fData, data, len); + fLen = len; +} + diff --git a/lib/pilotSerialDatabase.cc b/lib/pilotSerialDatabase.cc deleted file mode 100644 index a34e00c..0000000 --- a/lib/pilotSerialDatabase.cc +++ /dev/null @@ -1,432 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** -** Databases approached through DLP / Pilot-link look different, -** so this file defines an API for them. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 -#include - -#include - -#include - -#include -#include -#include - -#include "pilotRecord.h" -#include "pilotSerialDatabase.h" -#include "kpilotdevicelink.h" - -PilotSerialDatabase::PilotSerialDatabase(KPilotDeviceLink *l, - const TQString &dbName) : - PilotDatabase(dbName), - fDBName( dbName ), - fDBHandle(-1), - fDBSocket(l->pilotSocket()) -{ - FUNCTIONSETUP; - openDatabase(); -} - -PilotSerialDatabase::PilotSerialDatabase( KPilotDeviceLink *l, const DBInfo *info ) : - PilotDatabase( info ? Pilot::fromPilot( info->name ) : TQString() ), - fDBName( TQString() ), - fDBHandle( -1 ), - fDBSocket( l->pilotSocket() ) -{ - // Rather unclear why both the base class and this one have separate names. - fDBName = name(); - setDBOpen(false); - if (fDBName.isEmpty() || !info) - { - WARNINGKPILOT << "Bad database name requested." << endl; - return; - } - - int db; - if (dlp_OpenDB(fDBSocket, 0, dlpOpenReadWrite, info->name, &db) < 0) - { - WARNINGKPILOT << "Cannot open database on handheld." << endl; - return; - } - setDBHandle(db); - setDBOpen(true); -} - -PilotSerialDatabase::~PilotSerialDatabase() -{ - FUNCTIONSETUP; - closeDatabase(); -} - -TQString PilotSerialDatabase::dbPathName() const -{ - TQString s = CSL1("Pilot:"); - s.append(fDBName); - return s; -} - -// Reads the application block info -int PilotSerialDatabase::readAppBlock(unsigned char *buffer, int maxLen) -{ - FUNCTIONSETUP; - if (!isOpen()) - { - WARNINGKPILOT << "DB not open" << endl; - return -1; - } - pi_buffer_t *buf = pi_buffer_new(maxLen); - int r = dlp_ReadAppBlock(fDBSocket, getDBHandle(), 0 /* offset */, maxLen, buf); - if (r>=0) - { - memcpy(buffer, buf->data, KMAX(maxLen, r)); - } - pi_buffer_free(buf); - return r; -} - -// Writes the application block info. -int PilotSerialDatabase::writeAppBlock(unsigned char *buffer, int len) -{ - FUNCTIONSETUP; - if (!isOpen()) - { - WARNINGKPILOT << "DB not open" << endl; - return -1; - } - return dlp_WriteAppBlock(fDBSocket, getDBHandle(), buffer, len); -} - - // returns the number of records in the database -unsigned int PilotSerialDatabase::recordCount() const -{ - int idlen; - // dlp_ReadOpenDBInfo returns the number of bytes read and sets idlen to the # of recs - if (isOpen() && dlp_ReadOpenDBInfo(fDBSocket, getDBHandle(), &idlen)>0) - { - return idlen; - } - else - { - return 0; - } -} - - -// Returns a TQValueList of all record ids in the database. -TQValueList PilotSerialDatabase::idList() -{ - TQValueList idlist; - int idlen=recordCount(); - if (idlen<=0) return idlist; - - recordid_t *idarr=new recordid_t[idlen]; - int idlenread; - int r = dlp_ReadRecordIDList (fDBSocket, getDBHandle(), 0, 0, idlen, idarr, &idlenread); - - if ( (r<0) || (idlenread<1) ) - { - WARNINGKPILOT << "Failed to read ID list from database." << endl; - return idlist; - } - - // now create the TQValue list from the idarr: - for (idlen=0; idlen0xFFFFFF) - { - WARNINGKPILOT << "Encountered an invalid record id " - << id << endl; - return 0L; - } - pi_buffer_t *b = pi_buffer_new(InitialBufferSize); - if (dlp_ReadRecordById(fDBSocket,getDBHandle(),id,b,&index,&attr,&category) >= 0) - { - return new PilotRecord(b, attr, category, id); - } - return 0L; -} - -// Reads a record from database, returns the record length -PilotRecord *PilotSerialDatabase::readRecordByIndex(int index) -{ - FUNCTIONSETUPL(3); - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open" << endl; - return 0L; - } - - int attr, category; - recordid_t id; - PilotRecord *rec = 0L; - - pi_buffer_t *b = pi_buffer_new(InitialBufferSize); - if (dlp_ReadRecordByIndex(fDBSocket, getDBHandle(), index, - b, &id, &attr, &category) >= 0) - { - rec = new PilotRecord(b, attr, category, id); - } - - - return rec; -} - -// Reads the next record from database in category 'category' -PilotRecord *PilotSerialDatabase::readNextRecInCategory(int category) -{ - FUNCTIONSETUP; - int index, attr; - recordid_t id; - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open" << endl; - return 0L; - } - pi_buffer_t *b = pi_buffer_new(InitialBufferSize); - if (dlp_ReadNextRecInCategory(fDBSocket, getDBHandle(), - category,b,&id,&index,&attr) >= 0) - return new PilotRecord(b, attr, category, id); - return 0L; -} - -// Reads the next record from database that has the dirty flag set. -PilotRecord *PilotSerialDatabase::readNextModifiedRec(int *ind) -{ - FUNCTIONSETUP; - int index, attr, category; - recordid_t id; - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open" << endl; - return 0L; - } - pi_buffer_t *b = pi_buffer_new(InitialBufferSize); - if (dlp_ReadNextModifiedRec(fDBSocket, getDBHandle(), b, &id, &index, &attr, &category) >= 0) - { - if (ind) *ind=index; - return new PilotRecord(b, attr, category, id); - } - return 0L; -} - -// Writes a new record to database (if 'id' == 0 or id>0xFFFFFF, one will be assigned and returned in 'newid') -recordid_t PilotSerialDatabase::writeRecord(PilotRecord * newRecord) -{ - FUNCTIONSETUP; - recordid_t newid; - int success; - - if (!isOpen()) - { - WARNINGKPILOT << "DB not open" << endl; - return 0; - } - // Do some sanity checking to prevent invalid UniqueIDs from being written - // to the handheld (RecordIDs are only 3 bytes!!!). Under normal conditions - // this check should never yield true, so write out an error to indicate - // someone messed up full time... - if (newRecord->id()>0xFFFFFF) - { - WARNINGKPILOT << "Encountered an invalid record id " - << newRecord->id() << ", resetting it to zero." << endl; - newRecord->setID(0); - } - success = - dlp_WriteRecord(fDBSocket, getDBHandle(), - newRecord->attributes(), newRecord->id(), - newRecord->category(), newRecord->data(), - newRecord->size(), &newid); - if ( (newRecord->id() != newid) && (newid!=0) ) - newRecord->setID(newid); - return newid; -} - -// Deletes a record with the given recordid_t from the database, or all records, if all is set to true. The recordid_t will be ignored in this case -int PilotSerialDatabase::deleteRecord(recordid_t id, bool all) -{ - FUNCTIONSETUP; - if (!isOpen()) - { - WARNINGKPILOT <<"DB not open"< +** +** Databases approached through DLP / Pilot-link look different, +** so this file defines an API for them. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 +#include + +#include + +#include + +#include +#include +#include + +#include "pilotRecord.h" +#include "pilotSerialDatabase.h" +#include "kpilotdevicelink.h" + +PilotSerialDatabase::PilotSerialDatabase(KPilotDeviceLink *l, + const TQString &dbName) : + PilotDatabase(dbName), + fDBName( dbName ), + fDBHandle(-1), + fDBSocket(l->pilotSocket()) +{ + FUNCTIONSETUP; + openDatabase(); +} + +PilotSerialDatabase::PilotSerialDatabase( KPilotDeviceLink *l, const DBInfo *info ) : + PilotDatabase( info ? Pilot::fromPilot( info->name ) : TQString() ), + fDBName( TQString() ), + fDBHandle( -1 ), + fDBSocket( l->pilotSocket() ) +{ + // Rather unclear why both the base class and this one have separate names. + fDBName = name(); + setDBOpen(false); + if (fDBName.isEmpty() || !info) + { + WARNINGKPILOT << "Bad database name requested." << endl; + return; + } + + int db; + if (dlp_OpenDB(fDBSocket, 0, dlpOpenReadWrite, info->name, &db) < 0) + { + WARNINGKPILOT << "Cannot open database on handheld." << endl; + return; + } + setDBHandle(db); + setDBOpen(true); +} + +PilotSerialDatabase::~PilotSerialDatabase() +{ + FUNCTIONSETUP; + closeDatabase(); +} + +TQString PilotSerialDatabase::dbPathName() const +{ + TQString s = CSL1("Pilot:"); + s.append(fDBName); + return s; +} + +// Reads the application block info +int PilotSerialDatabase::readAppBlock(unsigned char *buffer, int maxLen) +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return -1; + } + pi_buffer_t *buf = pi_buffer_new(maxLen); + int r = dlp_ReadAppBlock(fDBSocket, getDBHandle(), 0 /* offset */, maxLen, buf); + if (r>=0) + { + memcpy(buffer, buf->data, KMAX(maxLen, r)); + } + pi_buffer_free(buf); + return r; +} + +// Writes the application block info. +int PilotSerialDatabase::writeAppBlock(unsigned char *buffer, int len) +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return -1; + } + return dlp_WriteAppBlock(fDBSocket, getDBHandle(), buffer, len); +} + + // returns the number of records in the database +unsigned int PilotSerialDatabase::recordCount() const +{ + int idlen; + // dlp_ReadOpenDBInfo returns the number of bytes read and sets idlen to the # of recs + if (isOpen() && dlp_ReadOpenDBInfo(fDBSocket, getDBHandle(), &idlen)>0) + { + return idlen; + } + else + { + return 0; + } +} + + +// Returns a TQValueList of all record ids in the database. +TQValueList PilotSerialDatabase::idList() +{ + TQValueList idlist; + int idlen=recordCount(); + if (idlen<=0) return idlist; + + recordid_t *idarr=new recordid_t[idlen]; + int idlenread; + int r = dlp_ReadRecordIDList (fDBSocket, getDBHandle(), 0, 0, idlen, idarr, &idlenread); + + if ( (r<0) || (idlenread<1) ) + { + WARNINGKPILOT << "Failed to read ID list from database." << endl; + return idlist; + } + + // now create the TQValue list from the idarr: + for (idlen=0; idlen0xFFFFFF) + { + WARNINGKPILOT << "Encountered an invalid record id " + << id << endl; + return 0L; + } + pi_buffer_t *b = pi_buffer_new(InitialBufferSize); + if (dlp_ReadRecordById(fDBSocket,getDBHandle(),id,b,&index,&attr,&category) >= 0) + { + return new PilotRecord(b, attr, category, id); + } + return 0L; +} + +// Reads a record from database, returns the record length +PilotRecord *PilotSerialDatabase::readRecordByIndex(int index) +{ + FUNCTIONSETUPL(3); + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return 0L; + } + + int attr, category; + recordid_t id; + PilotRecord *rec = 0L; + + pi_buffer_t *b = pi_buffer_new(InitialBufferSize); + if (dlp_ReadRecordByIndex(fDBSocket, getDBHandle(), index, + b, &id, &attr, &category) >= 0) + { + rec = new PilotRecord(b, attr, category, id); + } + + + return rec; +} + +// Reads the next record from database in category 'category' +PilotRecord *PilotSerialDatabase::readNextRecInCategory(int category) +{ + FUNCTIONSETUP; + int index, attr; + recordid_t id; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return 0L; + } + pi_buffer_t *b = pi_buffer_new(InitialBufferSize); + if (dlp_ReadNextRecInCategory(fDBSocket, getDBHandle(), + category,b,&id,&index,&attr) >= 0) + return new PilotRecord(b, attr, category, id); + return 0L; +} + +// Reads the next record from database that has the dirty flag set. +PilotRecord *PilotSerialDatabase::readNextModifiedRec(int *ind) +{ + FUNCTIONSETUP; + int index, attr, category; + recordid_t id; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return 0L; + } + pi_buffer_t *b = pi_buffer_new(InitialBufferSize); + if (dlp_ReadNextModifiedRec(fDBSocket, getDBHandle(), b, &id, &index, &attr, &category) >= 0) + { + if (ind) *ind=index; + return new PilotRecord(b, attr, category, id); + } + return 0L; +} + +// Writes a new record to database (if 'id' == 0 or id>0xFFFFFF, one will be assigned and returned in 'newid') +recordid_t PilotSerialDatabase::writeRecord(PilotRecord * newRecord) +{ + FUNCTIONSETUP; + recordid_t newid; + int success; + + if (!isOpen()) + { + WARNINGKPILOT << "DB not open" << endl; + return 0; + } + // Do some sanity checking to prevent invalid UniqueIDs from being written + // to the handheld (RecordIDs are only 3 bytes!!!). Under normal conditions + // this check should never yield true, so write out an error to indicate + // someone messed up full time... + if (newRecord->id()>0xFFFFFF) + { + WARNINGKPILOT << "Encountered an invalid record id " + << newRecord->id() << ", resetting it to zero." << endl; + newRecord->setID(0); + } + success = + dlp_WriteRecord(fDBSocket, getDBHandle(), + newRecord->attributes(), newRecord->id(), + newRecord->category(), newRecord->data(), + newRecord->size(), &newid); + if ( (newRecord->id() != newid) && (newid!=0) ) + newRecord->setID(newid); + return newid; +} + +// Deletes a record with the given recordid_t from the database, or all records, if all is set to true. The recordid_t will be ignored in this case +int PilotSerialDatabase::deleteRecord(recordid_t id, bool all) +{ + FUNCTIONSETUP; + if (!isOpen()) + { + WARNINGKPILOT <<"DB not open"< ** Copyright (C) 2006 Adriaan de Groot ** -** See the .cc file for an explanation of what this file is for. +** See the .cpp file for an explanation of what this file is for. */ /* diff --git a/lib/pilotTodoEntry.cc b/lib/pilotTodoEntry.cc deleted file mode 100644 index 9d52ed8..0000000 --- a/lib/pilotTodoEntry.cc +++ /dev/null @@ -1,270 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** -** This is a C++ wrapper for the todo-list entry structures. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 - -#include -#include - -#include -#include - - -#include "pilotTodoEntry.h" - - -PilotTodoEntry::PilotTodoEntry() : - fDescriptionSize(0), - fNoteSize(0) -{ - FUNCTIONSETUP; - ::memset(&fTodoInfo, 0, sizeof(struct ToDo)); -} - -PilotTodoEntry::PilotTodoEntry(PilotRecord * rec) : - PilotRecordBase(rec), - fDescriptionSize(0), - fNoteSize(0) -{ - ::memset(&fTodoInfo, 0, sizeof(struct ToDo)); - if (rec) - { - pi_buffer_t b; - b.data = (unsigned char *) rec->data(); - b.allocated = b.used = rec->size(); - unpack_ToDo(&fTodoInfo, &b, todo_v1); - if (fTodoInfo.description) - { - // Assume size of buffer allocated is just large enough; - // count trailing NUL as well. - fDescriptionSize = strlen(fTodoInfo.description)+1; - } - if (fTodoInfo.note) - { - // Same - fNoteSize = strlen(fTodoInfo.note)+1; - } - } - -} - - -PilotTodoEntry::PilotTodoEntry(const PilotTodoEntry & e) : - PilotRecordBase( &e ), - fDescriptionSize(0), - fNoteSize(0) -{ - FUNCTIONSETUP; - ::memcpy(&fTodoInfo, &e.fTodoInfo, sizeof(fTodoInfo)); - // See PilotDateEntry::operator = for details - fTodoInfo.description = 0L; - fTodoInfo.note = 0L; - - setDescriptionP(e.getDescriptionP()); - setNoteP(e.getNoteP()); -} - - -PilotTodoEntry & PilotTodoEntry::operator = (const PilotTodoEntry & e) -{ - if (this != &e) - { - KPILOT_FREE(fTodoInfo.description); - KPILOT_FREE(fTodoInfo.note); - - ::memcpy(&fTodoInfo, &e.fTodoInfo, sizeof(fTodoInfo)); - // See PilotDateEntry::operator = for details - fTodoInfo.description = 0L; - fTodoInfo.note = 0L; - fDescriptionSize = 0; - fNoteSize = 0; - - setDescriptionP(e.getDescriptionP()); - setNoteP(e.getNoteP()); - - } - - return *this; -} - -TQString PilotTodoEntry::getTextRepresentation(TQt::TextFormat richText) -{ - TQString text, tmp; - TQString par = (richText==TQt::RichText) ?CSL1("

"): TQString(); - TQString ps = (richText==TQt::RichText) ?CSL1("

"):CSL1("\n"); - TQString br = (richText==TQt::RichText) ?CSL1("
"):CSL1("\n"); - - // title + name - text += par; - tmp= (richText==TQt::RichText) ?CSL1("%1"):CSL1("%1"); - text += tmp.arg(rtExpand(getDescription(), richText)); - text += ps; - - text += par; - if (getComplete()) - text += i18n("Completed"); - else - text += i18n("Not completed"); - text += ps; - - if (!getIndefinite()) - { - TQDate dt(readTm(getDueDate()).date()); - TQString dueDate(dt.toString(Qt::LocalDate)); - text+=par; - text+=i18n("Due date: %1").arg(dueDate); - text+=ps; - } - - text+=par; - text+=ps; - - text+=par; - text+=i18n("Priority: %1").arg(getPriority()); - text+=ps; - - if (!getNote().isEmpty()) - { - text += (richText==TQt::RichText) ?CSL1("
"):CSL1("-------------------------\n"); - text+=par; - text+= (richText==TQt::RichText) ?i18n("Note:
"):i18n("Note:\n"); - text+=rtExpand(getNote(), richText); - text+=ps; - } - - return text; -} - -PilotRecord *PilotTodoEntry::pack() const -{ - int i; - - pi_buffer_t *b = pi_buffer_new( sizeof(fTodoInfo) ); - i = pack_ToDo(const_cast(&fTodoInfo), b, todo_v1); - if (i<0) - { - return 0; - } - // pack_ToDo sets b->used - return new PilotRecord( b, this ); -} - -void PilotTodoEntry::setDescription(const TQString &desc) -{ - if (desc.length() < fDescriptionSize) - { - Pilot::toPilot(desc, fTodoInfo.description, fDescriptionSize); - } - else - { - setDescriptionP(Pilot::toPilot(desc),desc.length()); - } -} - -void PilotTodoEntry::setDescriptionP(const char *desc, int len) -{ - KPILOT_FREE(fTodoInfo.description); - if (desc && *desc) - { - if (-1 == len) - { - len=::strlen(desc); - } - - fDescriptionSize = len+1; - fTodoInfo.description = (char *)::malloc(len + 1); - if (fTodoInfo.description) - { - strncpy(fTodoInfo.description, desc, len); - fTodoInfo.description[len] = 0; - } - else - { - WARNINGKPILOT << "malloc() failed, description not set" - << endl; - } - } - else - { - fTodoInfo.description = 0L; - } -} - -TQString PilotTodoEntry::getDescription() const -{ - return Pilot::fromPilot(getDescriptionP()); -} - -void PilotTodoEntry::setNote(const TQString ¬e) -{ - if (note.length() < fNoteSize) - { - Pilot::toPilot(note, fTodoInfo.note, fNoteSize); - } - else - { - setNoteP(Pilot::toPilot(note),note.length()); - } -} - -void PilotTodoEntry::setNoteP(const char *note, int len) -{ - KPILOT_FREE(fTodoInfo.note); - if (note && *note) - { - if (-1 == len) - { - len=::strlen(note); - } - - fNoteSize = len+1; - fTodoInfo.note = (char *)::malloc(len + 1); - if (fTodoInfo.note) - { - strncpy(fTodoInfo.note, note, len); - fTodoInfo.note[len] = 0; - } - else - { - WARNINGKPILOT << "malloc() failed, note not set" << endl; - } - } - else - { - fTodoInfo.note = 0L; - } -} - -TQString PilotTodoEntry::getNote() const -{ - return Pilot::fromPilot(getNoteP()); -} - diff --git a/lib/pilotTodoEntry.cpp b/lib/pilotTodoEntry.cpp new file mode 100644 index 0000000..9d52ed8 --- /dev/null +++ b/lib/pilotTodoEntry.cpp @@ -0,0 +1,270 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** +** This is a C++ wrapper for the todo-list entry structures. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 + +#include +#include + +#include +#include + + +#include "pilotTodoEntry.h" + + +PilotTodoEntry::PilotTodoEntry() : + fDescriptionSize(0), + fNoteSize(0) +{ + FUNCTIONSETUP; + ::memset(&fTodoInfo, 0, sizeof(struct ToDo)); +} + +PilotTodoEntry::PilotTodoEntry(PilotRecord * rec) : + PilotRecordBase(rec), + fDescriptionSize(0), + fNoteSize(0) +{ + ::memset(&fTodoInfo, 0, sizeof(struct ToDo)); + if (rec) + { + pi_buffer_t b; + b.data = (unsigned char *) rec->data(); + b.allocated = b.used = rec->size(); + unpack_ToDo(&fTodoInfo, &b, todo_v1); + if (fTodoInfo.description) + { + // Assume size of buffer allocated is just large enough; + // count trailing NUL as well. + fDescriptionSize = strlen(fTodoInfo.description)+1; + } + if (fTodoInfo.note) + { + // Same + fNoteSize = strlen(fTodoInfo.note)+1; + } + } + +} + + +PilotTodoEntry::PilotTodoEntry(const PilotTodoEntry & e) : + PilotRecordBase( &e ), + fDescriptionSize(0), + fNoteSize(0) +{ + FUNCTIONSETUP; + ::memcpy(&fTodoInfo, &e.fTodoInfo, sizeof(fTodoInfo)); + // See PilotDateEntry::operator = for details + fTodoInfo.description = 0L; + fTodoInfo.note = 0L; + + setDescriptionP(e.getDescriptionP()); + setNoteP(e.getNoteP()); +} + + +PilotTodoEntry & PilotTodoEntry::operator = (const PilotTodoEntry & e) +{ + if (this != &e) + { + KPILOT_FREE(fTodoInfo.description); + KPILOT_FREE(fTodoInfo.note); + + ::memcpy(&fTodoInfo, &e.fTodoInfo, sizeof(fTodoInfo)); + // See PilotDateEntry::operator = for details + fTodoInfo.description = 0L; + fTodoInfo.note = 0L; + fDescriptionSize = 0; + fNoteSize = 0; + + setDescriptionP(e.getDescriptionP()); + setNoteP(e.getNoteP()); + + } + + return *this; +} + +TQString PilotTodoEntry::getTextRepresentation(TQt::TextFormat richText) +{ + TQString text, tmp; + TQString par = (richText==TQt::RichText) ?CSL1("

"): TQString(); + TQString ps = (richText==TQt::RichText) ?CSL1("

"):CSL1("\n"); + TQString br = (richText==TQt::RichText) ?CSL1("
"):CSL1("\n"); + + // title + name + text += par; + tmp= (richText==TQt::RichText) ?CSL1("%1"):CSL1("%1"); + text += tmp.arg(rtExpand(getDescription(), richText)); + text += ps; + + text += par; + if (getComplete()) + text += i18n("Completed"); + else + text += i18n("Not completed"); + text += ps; + + if (!getIndefinite()) + { + TQDate dt(readTm(getDueDate()).date()); + TQString dueDate(dt.toString(Qt::LocalDate)); + text+=par; + text+=i18n("Due date: %1").arg(dueDate); + text+=ps; + } + + text+=par; + text+=ps; + + text+=par; + text+=i18n("Priority: %1").arg(getPriority()); + text+=ps; + + if (!getNote().isEmpty()) + { + text += (richText==TQt::RichText) ?CSL1("
"):CSL1("-------------------------\n"); + text+=par; + text+= (richText==TQt::RichText) ?i18n("Note:
"):i18n("Note:\n"); + text+=rtExpand(getNote(), richText); + text+=ps; + } + + return text; +} + +PilotRecord *PilotTodoEntry::pack() const +{ + int i; + + pi_buffer_t *b = pi_buffer_new( sizeof(fTodoInfo) ); + i = pack_ToDo(const_cast(&fTodoInfo), b, todo_v1); + if (i<0) + { + return 0; + } + // pack_ToDo sets b->used + return new PilotRecord( b, this ); +} + +void PilotTodoEntry::setDescription(const TQString &desc) +{ + if (desc.length() < fDescriptionSize) + { + Pilot::toPilot(desc, fTodoInfo.description, fDescriptionSize); + } + else + { + setDescriptionP(Pilot::toPilot(desc),desc.length()); + } +} + +void PilotTodoEntry::setDescriptionP(const char *desc, int len) +{ + KPILOT_FREE(fTodoInfo.description); + if (desc && *desc) + { + if (-1 == len) + { + len=::strlen(desc); + } + + fDescriptionSize = len+1; + fTodoInfo.description = (char *)::malloc(len + 1); + if (fTodoInfo.description) + { + strncpy(fTodoInfo.description, desc, len); + fTodoInfo.description[len] = 0; + } + else + { + WARNINGKPILOT << "malloc() failed, description not set" + << endl; + } + } + else + { + fTodoInfo.description = 0L; + } +} + +TQString PilotTodoEntry::getDescription() const +{ + return Pilot::fromPilot(getDescriptionP()); +} + +void PilotTodoEntry::setNote(const TQString ¬e) +{ + if (note.length() < fNoteSize) + { + Pilot::toPilot(note, fTodoInfo.note, fNoteSize); + } + else + { + setNoteP(Pilot::toPilot(note),note.length()); + } +} + +void PilotTodoEntry::setNoteP(const char *note, int len) +{ + KPILOT_FREE(fTodoInfo.note); + if (note && *note) + { + if (-1 == len) + { + len=::strlen(note); + } + + fNoteSize = len+1; + fTodoInfo.note = (char *)::malloc(len + 1); + if (fTodoInfo.note) + { + strncpy(fTodoInfo.note, note, len); + fTodoInfo.note[len] = 0; + } + else + { + WARNINGKPILOT << "malloc() failed, note not set" << endl; + } + } + else + { + fTodoInfo.note = 0L; + } +} + +TQString PilotTodoEntry::getNote() const +{ + return Pilot::fromPilot(getNoteP()); +} + diff --git a/lib/plugin.cc b/lib/plugin.cc deleted file mode 100644 index 1013a34..0000000 --- a/lib/plugin.cc +++ /dev/null @@ -1,760 +0,0 @@ -/* KPilot -** -** Copyright (C) 2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** -** This file defines the base class of all KPilot conduit plugins configuration -** dialogs. This is necessary so that we have a fixed API to talk to from -** inside KPilot. -** -** The factories used by KPilot plugins are also documented here. -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "pilotSerialDatabase.h" -#include "pilotLocalDatabase.h" - -#include "plugin.moc" - -ConduitConfigBase::ConduitConfigBase(TQWidget *parent, - const char *name) : - TQObject(parent,name), - fModified(false), - fWidget(0L), - fConduitName(i18n("Unnamed")) -{ - FUNCTIONSETUP; -} - -ConduitConfigBase::~ConduitConfigBase() -{ - FUNCTIONSETUP; -} - -/* slot */ void ConduitConfigBase::modified() -{ - fModified=true; - emit changed(true); -} - -/* virtual */ TQString ConduitConfigBase::maybeSaveText() const -{ - FUNCTIONSETUP; - - return i18n("The %1 conduit's settings have been changed. Do you " - "want to save the changes before continuing?").arg(this->conduitName()); -} - -/* virtual */ bool ConduitConfigBase::maybeSave() -{ - FUNCTIONSETUP; - - if (!isModified()) return true; - - int r = KMessageBox::questionYesNoCancel(fWidget, - maybeSaveText(), - i18n("%1 Conduit").arg(this->conduitName()), KStdGuiItem::save(), KStdGuiItem::discard()); - if (r == KMessageBox::Cancel) return false; - if (r == KMessageBox::Yes) commit(); - return true; -} - -TQWidget *ConduitConfigBase::aboutPage(TQWidget *parent, TDEAboutData *ad) -{ - FUNCTIONSETUP; - - TQWidget *w = new TQWidget(parent, "aboutpage"); - - TQString s; - TQLabel *text; - TDEIconLoader *l = TDEGlobal::iconLoader(); - const TDEAboutData *p = ad ? ad : TDEGlobal::instance()->aboutData(); - - TQGridLayout *grid = new TQGridLayout(w, 5, 4, SPACING); - - grid->addColSpacing(0, SPACING); - grid->addColSpacing(4, SPACING); - - - TQPixmap applicationIcon = - l->loadIcon(TQString::fromLatin1(p->appName()), - TDEIcon::Desktop, - 64, TDEIcon::DefaultState, 0L, - true); - - if (applicationIcon.isNull()) - { - applicationIcon = l->loadIcon(TQString::fromLatin1("kpilot"), - TDEIcon::Desktop); - } - - text = new TQLabel(w); - // Experiment with a long non- string. Use that to find - // sensible widths for the columns. - // - text->setText(i18n("Send questions and comments to tdepim-users@kde.org")); - text->adjustSize(); - - int linewidth = text->size().width(); - int lineheight = text->size().height(); - - // Use the label to display the applciation icon - text->setText(TQString()); - text->setPixmap(applicationIcon); - text->adjustSize(); - grid->addWidget(text, 0, 1); - - - KActiveLabel *linktext = new KActiveLabel(w); - grid->addRowSpacing(1,kMax(100,6*lineheight)); - grid->addRowSpacing(2,kMax(100,6*lineheight)); - grid->addColSpacing(2,SPACING+linewidth/2); - grid->addColSpacing(3,SPACING+linewidth/2); - grid->setRowStretch(1,50); - grid->setRowStretch(2,50); - grid->setColStretch(2,50); - grid->setColStretch(3,50); - linktext->setMinimumSize(linewidth,kMax(260,60+12*lineheight)); - linktext->setFixedHeight(kMax(260,60+12*lineheight)); - linktext->setVScrollBarMode(TQScrollView::Auto/*AlwaysOn*/); - text = new TQLabel(w); - grid->addMultiCellWidget(text,0,0,2,3); - grid->addMultiCellWidget(linktext,1,2,1,3); - - // Now set the program and copyright information. - s = CSL1("

"); - s += p->programName(); - s += ' '; - s += p->version(); - s += CSL1("

"); - s += p->copyrightStatement() + CSL1("
"); - text->setText(s); - - linktext->append(p->shortDescription() + CSL1("
")); - - if (!p->homepage().isEmpty()) - { - s = TQString(); - s += CSL1("").arg(p->homepage()); - s += p->homepage(); - s += CSL1("
"); - linktext->append(s); - } - - s = TQString(); - s += i18n("Send questions and comments to %2.") - .arg( CSL1("tdepim-users@kde.org") ) - .arg( CSL1("tdepim-users@kde.org") ); - s += ' '; - s += i18n("Send bug reports to %2.") - .arg(p->bugAddress()) - .arg(p->bugAddress()); - s += ' '; - s += i18n("For trademark information, see the " - "KPilot User's Guide."); - s += CSL1("
"); - linktext->append(s); - linktext->append(TQString()); - - - - TQValueList pl = p->authors(); - TQValueList::ConstIterator i; - - s = i18n("Authors: "); - - TQString comma = CSL1(", "); - - unsigned int count=1; - for (i=pl.begin(); i!=pl.end(); ++i) - { - s.append(CSL1("%1 (%2)%3") - .arg((*i).name()) - .arg((*i).task()) - .arg(countappend(s); - - s = TQString(); - pl = p->credits(); - if (pl.count()>0) - { - count=1; - s.append(i18n("Credits: ")); - for (i=pl.begin(); i!=pl.end(); ++i) - { - s.append(CSL1("%1 (%2)%3") - .arg((*i).name()) - .arg((*i).task()) - .arg(countappend(s); - linktext->ensureVisible(0,0); - - w->adjustSize(); - - return w; -} - -/* static */ void ConduitConfigBase::addAboutPage(TQTabWidget *tw, - TDEAboutData *ad) -{ - FUNCTIONSETUP; - - Q_ASSERT(tw); - - TQWidget *w = aboutPage(tw,ad); - TQSize sz = w->size(); - - if (sz.width() < tw->size().width()) - { - sz.setWidth(tw->size().width()); - } - if (sz.height() < tw->size().height()) - { - sz.setHeight(tw->size().height()); - } - - tw->resize(sz); - tw->addTab(w, i18n("About")); - tw->adjustSize(); -} - - - -ConduitAction::ConduitAction(KPilotLink *p, - const char *name, - const TQStringList &args) : - SyncAction(p,name), - fDatabase(0L), - fLocalDatabase(0L), - fCtrHH(0L), - fCtrPC(0L), - fSyncDirection(args), - fConflictResolution(SyncAction::eAskUser), - fFirstSync(false) -{ - FUNCTIONSETUP; - - TQString cResolution(args.grep(TQRegExp(CSL1("--conflictResolution \\d*"))).first()); - if (cResolution.isEmpty()) - { - fConflictResolution=(SyncAction::ConflictResolution) - cResolution.replace(TQRegExp(CSL1("--conflictResolution (\\d*)")), CSL1("\\1")).toInt(); - } - - for (TQStringList::ConstIterator it = args.begin(); - it != args.end(); - ++it) - { - DEBUGKPILOT << fname << ": " << *it << endl; - } - - DEBUGKPILOT << fname << ": Direction=" << fSyncDirection.name() << endl; - fCtrHH = new CUDCounter(i18n("Handheld")); - fCtrPC = new CUDCounter(i18n("PC")); -} - -/* virtual */ ConduitAction::~ConduitAction() -{ - FUNCTIONSETUP; - - KPILOT_DELETE(fDatabase); - KPILOT_DELETE(fLocalDatabase); - - KPILOT_DELETE(fCtrHH); - KPILOT_DELETE(fCtrPC); -} - -bool ConduitAction::openDatabases(const TQString &name, bool *retrieved) -{ - FUNCTIONSETUP; - - DEBUGKPILOT << fname - << ": Trying to open database " - << name << endl; - DEBUGKPILOT << fname - << ": Mode=" - << (syncMode().isTest() ? "test " : "") - << (syncMode().isLocal() ? "local " : "") - << endl ; - - KPILOT_DELETE(fLocalDatabase); - - TQString localPathName = PilotLocalDatabase::getDBPath() + name; - - // we always want to use the conduits/ directory for our local - // databases. this keeps our backups and data that our conduits use - // for record keeping separate - localPathName.replace(CSL1("DBBackup/"), CSL1("conduits/")); - - DEBUGKPILOT << fname << ": localPathName: [" << localPathName - << "]" << endl; - - PilotLocalDatabase *localDB = new PilotLocalDatabase( localPathName ); - - if (!localDB) - { - WARNINGKPILOT << "Could not initialize object for local copy of database \"" - << name - << "\"" << endl; - if (retrieved) *retrieved = false; - return false; - } - - // if there is no backup db yet, fetch it from the palm, open it and set the full sync flag. - if (!localDB->isOpen() ) - { - TQString dbpath(localDB->dbPathName()); - KPILOT_DELETE(localDB); - DEBUGKPILOT << fname - << ": Backup database " << dbpath - << " not found." << endl; - struct DBInfo dbinfo; - -// TODO Extend findDatabase() with extra overload? - if (deviceLink()->findDatabase(Pilot::toPilot( name ), &dbinfo)<0 ) - { - WARNINGKPILOT << "Could not get DBInfo for " << name << endl; - if (retrieved) *retrieved = false; - return false; - } - - DEBUGKPILOT << fname - << ": Found Palm database: " << dbinfo.name <" << endl; - TDEStandardDirs::makeDir(path); - } - if (!TDEStandardDirs::exists(path)) - { - DEBUGKPILOT << fname << ": Database directory does not exist." << endl; - if (retrieved) *retrieved = false; - return false; - } - - if (!deviceLink()->retrieveDatabase(dbpath, &dbinfo) ) - { - WARNINGKPILOT << "Could not retrieve database " - << name << " from the handheld." << endl; - if (retrieved) *retrieved = false; - return false; - } - localDB = new PilotLocalDatabase( localPathName ); - if (!localDB || !localDB->isOpen()) - { - WARNINGKPILOT << "local backup of database " << name << " could not be initialized." << endl; - if (retrieved) *retrieved = false; - return false; - } - if (retrieved) *retrieved=true; - } - fLocalDatabase = localDB; - - fDatabase = deviceLink()->database( name ); - - if (!fDatabase) - { - WARNINGKPILOT << "Could not open database \"" - << name - << "\" on the pilot." - << endl; - } - else - { - fCtrHH->setStartCount(fDatabase->recordCount()); - } - - return (fDatabase && fDatabase->isOpen() && - fLocalDatabase && fLocalDatabase->isOpen() ); -} - - -bool ConduitAction::changeSync(SyncMode::Mode m) -{ - FUNCTIONSETUP; - - if ( fSyncDirection.isSync() && SyncMode::eFullSync == m) - { - fSyncDirection.setMode(m); - return true; - } - return false; -} - -void ConduitAction::finished() -{ - FUNCTIONSETUP; - - if (fDatabase && fCtrHH) - fCtrHH->setEndCount(fDatabase->recordCount()); - - if (fCtrHH && fCtrPC) - { - addSyncLogEntry(fCtrHH->moo() +"\n",false); - DEBUGKPILOT << fname << ": " << fCtrHH->moo() << endl; - addSyncLogEntry(fCtrPC->moo() +"\n",false); - DEBUGKPILOT << fname << ": " << fCtrPC->moo() << endl; - - // STEP2 of making sure we don't delete our little user's - // precious data... - // sanity checks for handheld... - int hhVolatility = fCtrHH->percentDeleted() + - fCtrHH->percentUpdated() + - fCtrHH->percentCreated(); - - int pcVolatility = fCtrPC->percentDeleted() + - fCtrPC->percentUpdated() + - fCtrPC->percentCreated(); - - // TODO: allow user to configure this... - // this is a percentage... - int allowedVolatility = 70; - - TQString caption = i18n("Large Changes Detected"); - // args are already i18n'd - TQString query = i18n("The %1 conduit has made a " - "large number of changes to your %2. Do you want " - "to allow this change?\nDetails:\n\t%3"); - - if (hhVolatility > allowedVolatility) - { - query = query.arg(fConduitName) - .arg(fCtrHH->type()).arg(fCtrHH->moo()); - - DEBUGKPILOT << fname << ": Yikes, lots of volatility " - << "caught. Check with user: [" << query - << "]." << endl; - - /* - int rc = questionYesNo(query, caption, - TQString(), 0 ); - if (rc == KMessageBox::Yes) - { - // TODO: add commit and rollback code. - // note: this will require some thinking, - // since we have to undo changes to the - // pilot databases, changes to the PC - // resources, changes to the mappings files - // (record id mapping, etc.) - } - */ - } - - - } - -} - - -ConduitProxy::ConduitProxy(KPilotLink *p, - const TQString &name, - const SyncAction::SyncMode &m) : - ConduitAction(p,name.latin1(),m.list()), - fDesktopName(name) -{ - FUNCTIONSETUP; -} - -/* virtual */ bool ConduitProxy::exec() -{ - FUNCTIONSETUP; - - // query that service - TDESharedPtr < KService > o = KService::serviceByDesktopName(fDesktopName); - if (!o) - { - WARNINGKPILOT << "Can't find desktop file for conduit " - << fDesktopName - << endl; - addSyncLogEntry(i18n("Could not find conduit %1.").arg(fDesktopName)); - return false; - } - - - // load the lib - fLibraryName = o->library(); - DEBUGKPILOT << fname - << ": Loading desktop " - << fDesktopName - << " with lib " - << fLibraryName - << endl; - - KLibrary *library = KLibLoader::self()->library( - TQFile::encodeName(fLibraryName)); - if (!library) - { - WARNINGKPILOT << "Can't load library " - << fLibraryName - << " - " - << KLibLoader::self()->lastErrorMessage() - << endl; - addSyncLogEntry(i18n("Could not load conduit %1.").arg(fDesktopName)); - return false; - } - - unsigned long version = PluginUtility::pluginVersion(library); - if ( Pilot::PLUGIN_API != version ) - { - WARNINGKPILOT << "Library " - << fLibraryName - << " has version " - << version - << endl; - addSyncLogEntry(i18n("Conduit %1 has wrong version (%2).").arg(fDesktopName).arg(version)); - return false; - } - - KLibFactory *factory = library->factory(); - if (!factory) - { - WARNINGKPILOT << "Can't find factory in library " - << fLibraryName - << endl; - addSyncLogEntry(i18n("Could not initialize conduit %1.").arg(fDesktopName)); - return false; - } - - TQStringList l = syncMode().list(); - - DEBUGKPILOT << fname << ": Flags: " << syncMode().name() << endl; - - TQObject *object = factory->create(fHandle,name(),"SyncAction",l); - - if (!object) - { - WARNINGKPILOT << "Can't create SyncAction." << endl; - addSyncLogEntry(i18n("Could not create conduit %1.").arg(fDesktopName)); - return false; - } - - fConduit = dynamic_cast(object); - - if (!fConduit) - { - WARNINGKPILOT << "Can't cast to ConduitAction." << endl; - addSyncLogEntry(i18n("Could not create conduit %1.").arg(fDesktopName)); - return false; - } - - addSyncLogEntry(i18n("[Conduit %1]").arg(fDesktopName)); - - // Handle the syncDone signal properly & unload the conduit. - TQObject::connect(fConduit,TQT_SIGNAL(syncDone(SyncAction *)), - this,TQT_SLOT(execDone(SyncAction *))); - // Proxy all the log and error messages. - TQObject::connect(fConduit,TQT_SIGNAL(logMessage(const TQString &)), - this,TQT_SIGNAL(logMessage(const TQString &))); - TQObject::connect(fConduit,TQT_SIGNAL(logError(const TQString &)), - this,TQT_SIGNAL(logError(const TQString &))); - TQObject::connect(fConduit,TQT_SIGNAL(logProgress(const TQString &,int)), - this,TQT_SIGNAL(logProgress(const TQString &,int))); - - TQTimer::singleShot(0,fConduit,TQT_SLOT(execConduit())); - return true; -} - -void ConduitProxy::execDone(SyncAction *p) -{ - FUNCTIONSETUP; - - if (p!=fConduit) - { - WARNINGKPILOT << "Unknown conduit @" - << (void *) p - << " finished." - << endl; - emit syncDone(this); - return; - } - - // give our worker a chance to sanity check the results... - fConduit->finished(); - - addSyncLogEntry(CSL1("\n"),false); // Put bits of the conduit logs on separate lines - - KPILOT_DELETE(p); - - emit syncDone(this); -} - - -namespace PluginUtility -{ - -TQString findArgument(const TQStringList &a, const TQString &arg) -{ - FUNCTIONSETUP; - - TQString search; - - if (arg.startsWith( CSL1("--") )) - { - search = arg; - } - else - { - search = CSL1("--") + arg; - } - search.append( CSL1("=") ); - - - TQStringList::ConstIterator end = a.end(); - for (TQStringList::ConstIterator i = a.begin(); i != end; ++i) - { - if ((*i).startsWith( search )) - { - TQString s = (*i).mid(search.length()); - return s; - } - } - - return TQString(); -} - -/* static */ bool isRunning(const TQCString &n) -{ - DCOPClient *dcop = TDEApplication::kApplication()->dcopClient(); - QCStringList apps = dcop->registeredApplications(); - return apps.contains(n); -} - - -/* static */ unsigned long pluginVersion(const KLibrary *lib) -{ - TQString symbol = CSL1("version_"); - symbol.append(lib->name()); - - if (!lib->hasSymbol(symbol.latin1())) return 0; - - unsigned long *p = (unsigned long *)(lib->symbol(symbol.latin1())); - return *p; -} - - -/* static */ TQString pluginVersionString(const KLibrary *lib) -{ - TQString symbol= CSL1("id_"); - symbol.append(lib->name()); - - if (!lib->hasSymbol(symbol.latin1())) return TQString(); - - return TQString::fromLatin1(*((const char **)(lib->symbol(symbol.latin1())))); -} - - -} - - -CUDCounter::CUDCounter(TQString s) : - fC(0),fU(0),fD(0),fStart(0),fEnd(0),fType(s) -{ -} - -void CUDCounter::created(unsigned int c) -{ - fC += c; -} - -void CUDCounter::updated(unsigned int c) -{ - fU += c; -} - -void CUDCounter::deleted(unsigned int c) -{ - fD += c; -} - -void CUDCounter::setStartCount(unsigned int t) -{ - fStart = t; -} - -void CUDCounter::setEndCount(unsigned int t) -{ - fEnd = t; -} - -TQString CUDCounter::moo() const -{ - TQString result = fType + ": " + - i18n("Start: %1. End: %2. ").arg(fStart).arg(fEnd); - - if (fC > 0) result += i18n("%1 new. ").arg(fC); - if (fU > 0) result += i18n("%1 changed. ").arg(fU); - if (fD > 0) result += i18n("%1 deleted. ").arg(fD); - - if ( (fC+fU+fD) <= 0) result += i18n("No changes made. "); - - return result; -} - - diff --git a/lib/plugin.cpp b/lib/plugin.cpp new file mode 100644 index 0000000..1013a34 --- /dev/null +++ b/lib/plugin.cpp @@ -0,0 +1,760 @@ +/* KPilot +** +** Copyright (C) 2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** +** This file defines the base class of all KPilot conduit plugins configuration +** dialogs. This is necessary so that we have a fixed API to talk to from +** inside KPilot. +** +** The factories used by KPilot plugins are also documented here. +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pilotSerialDatabase.h" +#include "pilotLocalDatabase.h" + +#include "plugin.moc" + +ConduitConfigBase::ConduitConfigBase(TQWidget *parent, + const char *name) : + TQObject(parent,name), + fModified(false), + fWidget(0L), + fConduitName(i18n("Unnamed")) +{ + FUNCTIONSETUP; +} + +ConduitConfigBase::~ConduitConfigBase() +{ + FUNCTIONSETUP; +} + +/* slot */ void ConduitConfigBase::modified() +{ + fModified=true; + emit changed(true); +} + +/* virtual */ TQString ConduitConfigBase::maybeSaveText() const +{ + FUNCTIONSETUP; + + return i18n("The %1 conduit's settings have been changed. Do you " + "want to save the changes before continuing?").arg(this->conduitName()); +} + +/* virtual */ bool ConduitConfigBase::maybeSave() +{ + FUNCTIONSETUP; + + if (!isModified()) return true; + + int r = KMessageBox::questionYesNoCancel(fWidget, + maybeSaveText(), + i18n("%1 Conduit").arg(this->conduitName()), KStdGuiItem::save(), KStdGuiItem::discard()); + if (r == KMessageBox::Cancel) return false; + if (r == KMessageBox::Yes) commit(); + return true; +} + +TQWidget *ConduitConfigBase::aboutPage(TQWidget *parent, TDEAboutData *ad) +{ + FUNCTIONSETUP; + + TQWidget *w = new TQWidget(parent, "aboutpage"); + + TQString s; + TQLabel *text; + TDEIconLoader *l = TDEGlobal::iconLoader(); + const TDEAboutData *p = ad ? ad : TDEGlobal::instance()->aboutData(); + + TQGridLayout *grid = new TQGridLayout(w, 5, 4, SPACING); + + grid->addColSpacing(0, SPACING); + grid->addColSpacing(4, SPACING); + + + TQPixmap applicationIcon = + l->loadIcon(TQString::fromLatin1(p->appName()), + TDEIcon::Desktop, + 64, TDEIcon::DefaultState, 0L, + true); + + if (applicationIcon.isNull()) + { + applicationIcon = l->loadIcon(TQString::fromLatin1("kpilot"), + TDEIcon::Desktop); + } + + text = new TQLabel(w); + // Experiment with a long non- string. Use that to find + // sensible widths for the columns. + // + text->setText(i18n("Send questions and comments to tdepim-users@kde.org")); + text->adjustSize(); + + int linewidth = text->size().width(); + int lineheight = text->size().height(); + + // Use the label to display the applciation icon + text->setText(TQString()); + text->setPixmap(applicationIcon); + text->adjustSize(); + grid->addWidget(text, 0, 1); + + + KActiveLabel *linktext = new KActiveLabel(w); + grid->addRowSpacing(1,kMax(100,6*lineheight)); + grid->addRowSpacing(2,kMax(100,6*lineheight)); + grid->addColSpacing(2,SPACING+linewidth/2); + grid->addColSpacing(3,SPACING+linewidth/2); + grid->setRowStretch(1,50); + grid->setRowStretch(2,50); + grid->setColStretch(2,50); + grid->setColStretch(3,50); + linktext->setMinimumSize(linewidth,kMax(260,60+12*lineheight)); + linktext->setFixedHeight(kMax(260,60+12*lineheight)); + linktext->setVScrollBarMode(TQScrollView::Auto/*AlwaysOn*/); + text = new TQLabel(w); + grid->addMultiCellWidget(text,0,0,2,3); + grid->addMultiCellWidget(linktext,1,2,1,3); + + // Now set the program and copyright information. + s = CSL1("

"); + s += p->programName(); + s += ' '; + s += p->version(); + s += CSL1("

"); + s += p->copyrightStatement() + CSL1("
"); + text->setText(s); + + linktext->append(p->shortDescription() + CSL1("
")); + + if (!p->homepage().isEmpty()) + { + s = TQString(); + s += CSL1("").arg(p->homepage()); + s += p->homepage(); + s += CSL1("
"); + linktext->append(s); + } + + s = TQString(); + s += i18n("Send questions and comments to %2.") + .arg( CSL1("tdepim-users@kde.org") ) + .arg( CSL1("tdepim-users@kde.org") ); + s += ' '; + s += i18n("Send bug reports to %2.") + .arg(p->bugAddress()) + .arg(p->bugAddress()); + s += ' '; + s += i18n("For trademark information, see the " + "KPilot User's Guide."); + s += CSL1("
"); + linktext->append(s); + linktext->append(TQString()); + + + + TQValueList pl = p->authors(); + TQValueList::ConstIterator i; + + s = i18n("Authors: "); + + TQString comma = CSL1(", "); + + unsigned int count=1; + for (i=pl.begin(); i!=pl.end(); ++i) + { + s.append(CSL1("%1 (%2)%3") + .arg((*i).name()) + .arg((*i).task()) + .arg(countappend(s); + + s = TQString(); + pl = p->credits(); + if (pl.count()>0) + { + count=1; + s.append(i18n("Credits: ")); + for (i=pl.begin(); i!=pl.end(); ++i) + { + s.append(CSL1("%1 (%2)%3") + .arg((*i).name()) + .arg((*i).task()) + .arg(countappend(s); + linktext->ensureVisible(0,0); + + w->adjustSize(); + + return w; +} + +/* static */ void ConduitConfigBase::addAboutPage(TQTabWidget *tw, + TDEAboutData *ad) +{ + FUNCTIONSETUP; + + Q_ASSERT(tw); + + TQWidget *w = aboutPage(tw,ad); + TQSize sz = w->size(); + + if (sz.width() < tw->size().width()) + { + sz.setWidth(tw->size().width()); + } + if (sz.height() < tw->size().height()) + { + sz.setHeight(tw->size().height()); + } + + tw->resize(sz); + tw->addTab(w, i18n("About")); + tw->adjustSize(); +} + + + +ConduitAction::ConduitAction(KPilotLink *p, + const char *name, + const TQStringList &args) : + SyncAction(p,name), + fDatabase(0L), + fLocalDatabase(0L), + fCtrHH(0L), + fCtrPC(0L), + fSyncDirection(args), + fConflictResolution(SyncAction::eAskUser), + fFirstSync(false) +{ + FUNCTIONSETUP; + + TQString cResolution(args.grep(TQRegExp(CSL1("--conflictResolution \\d*"))).first()); + if (cResolution.isEmpty()) + { + fConflictResolution=(SyncAction::ConflictResolution) + cResolution.replace(TQRegExp(CSL1("--conflictResolution (\\d*)")), CSL1("\\1")).toInt(); + } + + for (TQStringList::ConstIterator it = args.begin(); + it != args.end(); + ++it) + { + DEBUGKPILOT << fname << ": " << *it << endl; + } + + DEBUGKPILOT << fname << ": Direction=" << fSyncDirection.name() << endl; + fCtrHH = new CUDCounter(i18n("Handheld")); + fCtrPC = new CUDCounter(i18n("PC")); +} + +/* virtual */ ConduitAction::~ConduitAction() +{ + FUNCTIONSETUP; + + KPILOT_DELETE(fDatabase); + KPILOT_DELETE(fLocalDatabase); + + KPILOT_DELETE(fCtrHH); + KPILOT_DELETE(fCtrPC); +} + +bool ConduitAction::openDatabases(const TQString &name, bool *retrieved) +{ + FUNCTIONSETUP; + + DEBUGKPILOT << fname + << ": Trying to open database " + << name << endl; + DEBUGKPILOT << fname + << ": Mode=" + << (syncMode().isTest() ? "test " : "") + << (syncMode().isLocal() ? "local " : "") + << endl ; + + KPILOT_DELETE(fLocalDatabase); + + TQString localPathName = PilotLocalDatabase::getDBPath() + name; + + // we always want to use the conduits/ directory for our local + // databases. this keeps our backups and data that our conduits use + // for record keeping separate + localPathName.replace(CSL1("DBBackup/"), CSL1("conduits/")); + + DEBUGKPILOT << fname << ": localPathName: [" << localPathName + << "]" << endl; + + PilotLocalDatabase *localDB = new PilotLocalDatabase( localPathName ); + + if (!localDB) + { + WARNINGKPILOT << "Could not initialize object for local copy of database \"" + << name + << "\"" << endl; + if (retrieved) *retrieved = false; + return false; + } + + // if there is no backup db yet, fetch it from the palm, open it and set the full sync flag. + if (!localDB->isOpen() ) + { + TQString dbpath(localDB->dbPathName()); + KPILOT_DELETE(localDB); + DEBUGKPILOT << fname + << ": Backup database " << dbpath + << " not found." << endl; + struct DBInfo dbinfo; + +// TODO Extend findDatabase() with extra overload? + if (deviceLink()->findDatabase(Pilot::toPilot( name ), &dbinfo)<0 ) + { + WARNINGKPILOT << "Could not get DBInfo for " << name << endl; + if (retrieved) *retrieved = false; + return false; + } + + DEBUGKPILOT << fname + << ": Found Palm database: " << dbinfo.name <" << endl; + TDEStandardDirs::makeDir(path); + } + if (!TDEStandardDirs::exists(path)) + { + DEBUGKPILOT << fname << ": Database directory does not exist." << endl; + if (retrieved) *retrieved = false; + return false; + } + + if (!deviceLink()->retrieveDatabase(dbpath, &dbinfo) ) + { + WARNINGKPILOT << "Could not retrieve database " + << name << " from the handheld." << endl; + if (retrieved) *retrieved = false; + return false; + } + localDB = new PilotLocalDatabase( localPathName ); + if (!localDB || !localDB->isOpen()) + { + WARNINGKPILOT << "local backup of database " << name << " could not be initialized." << endl; + if (retrieved) *retrieved = false; + return false; + } + if (retrieved) *retrieved=true; + } + fLocalDatabase = localDB; + + fDatabase = deviceLink()->database( name ); + + if (!fDatabase) + { + WARNINGKPILOT << "Could not open database \"" + << name + << "\" on the pilot." + << endl; + } + else + { + fCtrHH->setStartCount(fDatabase->recordCount()); + } + + return (fDatabase && fDatabase->isOpen() && + fLocalDatabase && fLocalDatabase->isOpen() ); +} + + +bool ConduitAction::changeSync(SyncMode::Mode m) +{ + FUNCTIONSETUP; + + if ( fSyncDirection.isSync() && SyncMode::eFullSync == m) + { + fSyncDirection.setMode(m); + return true; + } + return false; +} + +void ConduitAction::finished() +{ + FUNCTIONSETUP; + + if (fDatabase && fCtrHH) + fCtrHH->setEndCount(fDatabase->recordCount()); + + if (fCtrHH && fCtrPC) + { + addSyncLogEntry(fCtrHH->moo() +"\n",false); + DEBUGKPILOT << fname << ": " << fCtrHH->moo() << endl; + addSyncLogEntry(fCtrPC->moo() +"\n",false); + DEBUGKPILOT << fname << ": " << fCtrPC->moo() << endl; + + // STEP2 of making sure we don't delete our little user's + // precious data... + // sanity checks for handheld... + int hhVolatility = fCtrHH->percentDeleted() + + fCtrHH->percentUpdated() + + fCtrHH->percentCreated(); + + int pcVolatility = fCtrPC->percentDeleted() + + fCtrPC->percentUpdated() + + fCtrPC->percentCreated(); + + // TODO: allow user to configure this... + // this is a percentage... + int allowedVolatility = 70; + + TQString caption = i18n("Large Changes Detected"); + // args are already i18n'd + TQString query = i18n("The %1 conduit has made a " + "large number of changes to your %2. Do you want " + "to allow this change?\nDetails:\n\t%3"); + + if (hhVolatility > allowedVolatility) + { + query = query.arg(fConduitName) + .arg(fCtrHH->type()).arg(fCtrHH->moo()); + + DEBUGKPILOT << fname << ": Yikes, lots of volatility " + << "caught. Check with user: [" << query + << "]." << endl; + + /* + int rc = questionYesNo(query, caption, + TQString(), 0 ); + if (rc == KMessageBox::Yes) + { + // TODO: add commit and rollback code. + // note: this will require some thinking, + // since we have to undo changes to the + // pilot databases, changes to the PC + // resources, changes to the mappings files + // (record id mapping, etc.) + } + */ + } + + + } + +} + + +ConduitProxy::ConduitProxy(KPilotLink *p, + const TQString &name, + const SyncAction::SyncMode &m) : + ConduitAction(p,name.latin1(),m.list()), + fDesktopName(name) +{ + FUNCTIONSETUP; +} + +/* virtual */ bool ConduitProxy::exec() +{ + FUNCTIONSETUP; + + // query that service + TDESharedPtr < KService > o = KService::serviceByDesktopName(fDesktopName); + if (!o) + { + WARNINGKPILOT << "Can't find desktop file for conduit " + << fDesktopName + << endl; + addSyncLogEntry(i18n("Could not find conduit %1.").arg(fDesktopName)); + return false; + } + + + // load the lib + fLibraryName = o->library(); + DEBUGKPILOT << fname + << ": Loading desktop " + << fDesktopName + << " with lib " + << fLibraryName + << endl; + + KLibrary *library = KLibLoader::self()->library( + TQFile::encodeName(fLibraryName)); + if (!library) + { + WARNINGKPILOT << "Can't load library " + << fLibraryName + << " - " + << KLibLoader::self()->lastErrorMessage() + << endl; + addSyncLogEntry(i18n("Could not load conduit %1.").arg(fDesktopName)); + return false; + } + + unsigned long version = PluginUtility::pluginVersion(library); + if ( Pilot::PLUGIN_API != version ) + { + WARNINGKPILOT << "Library " + << fLibraryName + << " has version " + << version + << endl; + addSyncLogEntry(i18n("Conduit %1 has wrong version (%2).").arg(fDesktopName).arg(version)); + return false; + } + + KLibFactory *factory = library->factory(); + if (!factory) + { + WARNINGKPILOT << "Can't find factory in library " + << fLibraryName + << endl; + addSyncLogEntry(i18n("Could not initialize conduit %1.").arg(fDesktopName)); + return false; + } + + TQStringList l = syncMode().list(); + + DEBUGKPILOT << fname << ": Flags: " << syncMode().name() << endl; + + TQObject *object = factory->create(fHandle,name(),"SyncAction",l); + + if (!object) + { + WARNINGKPILOT << "Can't create SyncAction." << endl; + addSyncLogEntry(i18n("Could not create conduit %1.").arg(fDesktopName)); + return false; + } + + fConduit = dynamic_cast(object); + + if (!fConduit) + { + WARNINGKPILOT << "Can't cast to ConduitAction." << endl; + addSyncLogEntry(i18n("Could not create conduit %1.").arg(fDesktopName)); + return false; + } + + addSyncLogEntry(i18n("[Conduit %1]").arg(fDesktopName)); + + // Handle the syncDone signal properly & unload the conduit. + TQObject::connect(fConduit,TQT_SIGNAL(syncDone(SyncAction *)), + this,TQT_SLOT(execDone(SyncAction *))); + // Proxy all the log and error messages. + TQObject::connect(fConduit,TQT_SIGNAL(logMessage(const TQString &)), + this,TQT_SIGNAL(logMessage(const TQString &))); + TQObject::connect(fConduit,TQT_SIGNAL(logError(const TQString &)), + this,TQT_SIGNAL(logError(const TQString &))); + TQObject::connect(fConduit,TQT_SIGNAL(logProgress(const TQString &,int)), + this,TQT_SIGNAL(logProgress(const TQString &,int))); + + TQTimer::singleShot(0,fConduit,TQT_SLOT(execConduit())); + return true; +} + +void ConduitProxy::execDone(SyncAction *p) +{ + FUNCTIONSETUP; + + if (p!=fConduit) + { + WARNINGKPILOT << "Unknown conduit @" + << (void *) p + << " finished." + << endl; + emit syncDone(this); + return; + } + + // give our worker a chance to sanity check the results... + fConduit->finished(); + + addSyncLogEntry(CSL1("\n"),false); // Put bits of the conduit logs on separate lines + + KPILOT_DELETE(p); + + emit syncDone(this); +} + + +namespace PluginUtility +{ + +TQString findArgument(const TQStringList &a, const TQString &arg) +{ + FUNCTIONSETUP; + + TQString search; + + if (arg.startsWith( CSL1("--") )) + { + search = arg; + } + else + { + search = CSL1("--") + arg; + } + search.append( CSL1("=") ); + + + TQStringList::ConstIterator end = a.end(); + for (TQStringList::ConstIterator i = a.begin(); i != end; ++i) + { + if ((*i).startsWith( search )) + { + TQString s = (*i).mid(search.length()); + return s; + } + } + + return TQString(); +} + +/* static */ bool isRunning(const TQCString &n) +{ + DCOPClient *dcop = TDEApplication::kApplication()->dcopClient(); + QCStringList apps = dcop->registeredApplications(); + return apps.contains(n); +} + + +/* static */ unsigned long pluginVersion(const KLibrary *lib) +{ + TQString symbol = CSL1("version_"); + symbol.append(lib->name()); + + if (!lib->hasSymbol(symbol.latin1())) return 0; + + unsigned long *p = (unsigned long *)(lib->symbol(symbol.latin1())); + return *p; +} + + +/* static */ TQString pluginVersionString(const KLibrary *lib) +{ + TQString symbol= CSL1("id_"); + symbol.append(lib->name()); + + if (!lib->hasSymbol(symbol.latin1())) return TQString(); + + return TQString::fromLatin1(*((const char **)(lib->symbol(symbol.latin1())))); +} + + +} + + +CUDCounter::CUDCounter(TQString s) : + fC(0),fU(0),fD(0),fStart(0),fEnd(0),fType(s) +{ +} + +void CUDCounter::created(unsigned int c) +{ + fC += c; +} + +void CUDCounter::updated(unsigned int c) +{ + fU += c; +} + +void CUDCounter::deleted(unsigned int c) +{ + fD += c; +} + +void CUDCounter::setStartCount(unsigned int t) +{ + fStart = t; +} + +void CUDCounter::setEndCount(unsigned int t) +{ + fEnd = t; +} + +TQString CUDCounter::moo() const +{ + TQString result = fType + ": " + + i18n("Start: %1. End: %2. ").arg(fStart).arg(fEnd); + + if (fC > 0) result += i18n("%1 new. ").arg(fC); + if (fU > 0) result += i18n("%1 changed. ").arg(fU); + if (fD > 0) result += i18n("%1 deleted. ").arg(fD); + + if ( (fC+fU+fD) <= 0) result += i18n("No changes made. "); + + return result; +} + + diff --git a/lib/recordConduit.cc b/lib/recordConduit.cc deleted file mode 100644 index 7c92152..0000000 --- a/lib/recordConduit.cc +++ /dev/null @@ -1,1145 +0,0 @@ -/* KPilot -** -** Copyright (C) 2004 by Reinhold Kainhofer -** Based on the addressbook conduit: -** Copyright (C) 2000,2001 by Dan Pilone -** Copyright (C) 2000 Gregory Stern -** Copyright (C) 2002-2003 by Reinhold Kainhofer -** -** This conduit is the base class for all record-based conduits. -** all the sync logic is included in this class, and all child classes -** just have to implement some specific copying and conflict resolution -** methods. -*/ - -/* -** 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 -#include - -#include "pilotAppCategory.h" -#include "pilotSerialDatabase.h" -#include "pilotLocalDatabase.h" -#include "recordConduit.h" - - -// Something to allow us to check what revision -// the modules are that make up a binary distribution. -// -// -extern "C" -{ -long version_record_conduit = Pilot::PLUGIN_API; -} - - -/* virtual */ bool RecordConduitBase::exec() -{ - FUNCTIONSETUP; - fState = Initialize; - - setFirstSync(false); - - bool retrieved = false; - if (!openDatabases( fDBName, &retrieved)) - { - emit logError(i18n("Unable to open the %1 database on the handheld.").arg( fDBName ) ); - return false; - } - if (retrieved) setFirstSync(true); - - if (isFirstSync()) fIDList=fDatabase->idList(); - else fIDList=fDatabase->modifiedIDList(); - fIDListIterator = fIDList.begin(); - - fTimer = new TQTimer(this); - connect(fTimer,TQT_SIGNAL(timeout()),this,TQT_SLOT(process())); - fTimer->start(0,false); // Fire as often as possible to prompt processing - return true; -} - -/* virtual */ void RecordConduitBase::process() -{ - FUNCTIONSETUP; - SyncProgress p = Error; - -#ifdef DEBUG - DEBUGKPILOT << fname << ": From state " << name(fState) << endl; -#endif - - switch(fState) - { - case Initialize : - p = loadPC(); - break; - case PalmToPC : - p = palmRecToPC(); - break; - case PCToPalm : - p = pcRecToPalm(); - break; - case Cleanup : - p = cleanup(); - break; - } - -#ifdef DEBUG - DEBUGKPILOT << fname << ": Step returned " << name(p) << endl; -#endif - - switch(p) - { - case Error : - fTimer->stop(); - delayDone(); - return; - case NotDone : - // Return so we get called again. - return; - case Done : - // Get on with it. - break; - } - -#ifdef DEBUG - DEBUGKPILOT << fname << ": Step is done, moving to next state." << endl; -#endif - - // Here the previous call was done. - switch(fState) - { - case Initialize : - switch (syncMode().mode()) - { - case SyncMode::eRestore : - case SyncMode::eCopyPCToHH : /* These two don't copy Palm records to the PC */ - fState = PCToPalm; - break; - default : - fState = PalmToPC; - } - break; - case PalmToPC : - switch (syncMode().mode()) - { - case SyncMode::eBackup : - case SyncMode::eCopyHHToPC : /* These modes don't copy PC records back */ - fState = Cleanup; - break; - default : - fState = PCToPalm; - } - break; - case PCToPalm : - fState = Cleanup; - break; - case Cleanup : - fTimer->stop(); - delayDone(); - // No change in state, timer stopped and we're done. - break; - } - -#ifdef DEBUG - DEBUGKPILOT << fname << ": Next state is " << name(fState) << endl; -#endif - -} - - -TQString RecordConduitBase::name(RecordConduitBase::SyncProgress s) -{ - switch(s) - { - case RecordConduitBase::NotDone: - return CSL1("NotDone"); - case RecordConduitBase::Done: - return CSL1("Done"); - case RecordConduitBase::Error: - return CSL1("Error"); - } -} - - -TQString RecordConduitBase::name(RecordConduitBase::States s) -{ - switch(s) - { - case RecordConduitBase::Initialize: - return CSL1("Initialize"); - case RecordConduitBase::PalmToPC: - return CSL1("Handheld-to-PC"); - case RecordConduitBase::PCToPalm: - return CSL1("PC-to-Handheld"); - case RecordConduitBase::Cleanup: - return CSL1("Cleanup"); - } -} - - -#if 0 -/** make that entry on the pc archived (i.e. deleted on the handheld, - * while present on the pc, but not synced to the handheld */ -bool RecordConduit::PCData::makeArchived( RecordConduit::PCEntry *pcEntry ) -{ - if ( pcEntry ) { - pcEntry->makeArchived(); - setChanged( true ); - return true; - } else return false; -} - - -/* Builds the map which links record ids to uid's of PCEntry. This is the slow implementation, - * that should always work. subclasses should reimplement it to speed things up. -*/ -bool RecordConduit::PCData::mapContactsToPilot( TQMap &idContactMap ) -{ - FUNCTIONSETUP; - - idContactMap.clear(); - - Iterator it = begin(); - PCEntry *ent; - while ( !atEnd( it ) ) { - ent = *it; - recordid_t id( ent->recid() ); - if ( id != 0 ) { - idContactMap.insert( id, ent->uid() ); - } - ++it; - } -#ifdef DEBUG - DEBUGKPILOT << fname << ": Loaded " << idContactMap.size() << - " Entries on the pc and mapped them to records on the handheld. " << endl; -#endif - return true; -} - - - -/********************************************************************* - C O N S T R U C T O R - *********************************************************************/ - - - -bool RecordConduit::mArchiveDeleted = false; - -RecordConduit::RecordConduit(TQString name, KPilotDeviceLink * o, const char *n, const TQStringList & a): - ConduitAction(o, n, a), - mPCData(0), mPalmIndex(0), - mEntryMap(), mSyncedIds(), mAllIds() -{ - FUNCTIONSETUP; - fConduitName = name; -} - - - -RecordConduit::~RecordConduit() -{ - if ( mPCData ) KPILOT_DELETE(mPCData); -} - - - - - - -/********************************************************************* - S Y N C S T R U C T U R E - *********************************************************************/ - - - -/* virtual */ bool RecordConduit::exec() -{ - FUNCTIONSETUP; - - if ( !_prepare() ) return false; - - fFirstSync = false; - // Database names probably in latin1. - if( !openDatabases( dbName(), &fFirstSync ) ) - { - emit logError(i18n("Unable to open the %1 database on the handheld.").arg( dbName() ) ); - return false; - } - _getAppInfo(); - if( !mPCData->loadData() ) - { - emit logError( i18n("Unable to open %1.").arg( mPCData->description() ) ); - return false; - } - // get the addresseMap which maps Pilot unique record(address) id's to - // a Abbrowser Addressee; allows for easy lookup and comparisons - if ( mPCData->isEmpty() ) - fFirstSync = true; - else - mPCData->mapContactsToPilot( mEntryMap ); - fFirstSync = fFirstSync || ( mPCData->isEmpty() ); - - // perform syncing from palm to abbrowser - // iterate through all records in palm pilot - mPalmIndex = 0; - -#ifdef DEBUG - DEBUGKPILOT << fname << ": fullsync=" << isFullSync() << ", firstSync=" << isFirstSync() << endl; - DEBUGKPILOT << fname << ": " - << "syncDirection=" << getSyncDirection() << ", " -// << "archive = " << AbbrowserSettings::archiveDeleted() - << endl; - DEBUGKPILOT << fname << ": conflictRes="<< getConflictResolution() << endl; -// DEBUGKPILOT << fname << ": PilotStreetHome=" << AbbrowserSettings::pilotStreet() << ", PilotFaxHOme" << AbbrowserSettings::pilotFax() << endl; -#endif - - if ( !isFirstSync() ) - mAllIds=fDatabase->idList(); - - /* Note: - if eCopyPCToHH or eCopyHHToPC, first sync everything, then lookup - those entries on the receiving side that are not yet syncced and delete - them. Use slotDeleteUnsyncedPCRecords and slotDeleteUnsyncedHHRecords - for this, and no longer purge the whole addressbook before the sync to - prevent data loss in case of connection loss. */ - - TQTimer::singleShot(0, this, TQT_SLOT(slotPalmRecToPC())); - - return true; -} - - - -void RecordConduit::slotPalmRecToPC() -{ - FUNCTIONSETUP; - PilotRecord *palmRec = 0L, *backupRec = 0L; - - if ( getSyncDirection() == SyncAction::eCopyPCToHH ) - { - mPCIter = mPCData->begin(); - TQTimer::singleShot(0, this, TQT_SLOT(slotPCRecToPalm())); - return; - } - - if ( isFullSync() ) - palmRec = fDatabase->readRecordByIndex( mPalmIndex++ ); - else - palmRec = dynamic_cast (fDatabase)->readNextModifiedRec(); - - if ( !palmRec ) - { - mPCIter = mPCData->begin(); - TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) ); - return; - } - - // already synced, so skip: - if ( mSyncedIds.contains( palmRec->id() ) ) - { - KPILOT_DELETE( palmRec ); - TQTimer::singleShot( 0, this, TQT_SLOT( slotPalmRecToPC() ) ); - return; - } - - backupRec = fLocalDatabase->readRecordById( palmRec->id() ); - PilotRecord *compareRec = backupRec ? backupRec : palmRec; - PilotAppCategory *compareEntry = createPalmEntry( compareRec ); - PCEntry *pcEntry = findMatch( compareEntry ); - KPILOT_DELETE( compareEntry ); - - PilotAppCategory *backupEntry=0L; - if ( backupRec ) - backupEntry = createPalmEntry( backupRec ); - PilotAppCategory *palmEntry=0L; - if ( palmRec ) - palmEntry = createPalmEntry( palmRec ); - - syncEntry( pcEntry, backupEntry, palmEntry ); - - mSyncedIds.append( palmRec->id() ); - - KPILOT_DELETE( pcEntry ); - KPILOT_DELETE( palmEntry ); - KPILOT_DELETE( backupEntry ); - KPILOT_DELETE( palmRec ); - KPILOT_DELETE( backupRec ); - - TQTimer::singleShot(0, this, TQT_SLOT(slotPalmRecToPC())); -} - - - -void RecordConduit::slotPCRecToPalm() -{ - FUNCTIONSETUP; - - if ( ( getSyncDirection()==SyncAction::eCopyHHToPC ) || - mPCData->atEnd( mPCIter ) ) - { - mPalmIndex = 0; - TQTimer::singleShot( 0, this, TQT_SLOT( slotDeletedRecord() ) ); - return; - } - - PilotRecord *backupRec=0L; - PCEntry *pcEntry = *mPCIter; - ++mPCIter; - - // If marked as archived, don't sync! - if ( isArchived( pcEntry ) ) - { -#ifdef DEBUG - DEBUGKPILOT << fname << ": address with id " << pcEntry->uid() << - " marked archived, so don't sync." << endl; -#endif - KPILOT_DELETE( pcEntry ); - TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) ); - return; - } - - recordid_t recID( pcEntry->recid() ); - if ( recID == 0 ) - { - // it's a new item(no record ID and not inserted by the Palm -> PC sync), so add it - syncEntry( pcEntry, 0L, 0L ); - KPILOT_DELETE( pcEntry ); - TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) ); - return; - } - - // look into the list of already synced record ids to see if the PCEntry hasn't already been synced - if ( mSyncedIds.contains( recID ) ) - { -#ifdef DEBUG - DEBUGKPILOT << ": address with id " << recID << " already synced." << endl; -#endif - KPILOT_DELETE( pcEntry ); - TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) ); - return; - } - - - backupRec = fLocalDatabase->readRecordById( recID ); - // only update if no backup record or the backup record is not equal to the PCEntry - - PilotAppCategory*backupEntry=0L; - if ( backupRec ) - backupEntry = createPalmEntry( backupRec ); - if( !backupRec || isFirstSync() || !_equal( backupEntry, pcEntry ) ) - { - PilotRecord *palmRec = fDatabase->readRecordById( recID ); - PilotAppCategory *palmEntry=0L; - if (palmRec) - palmEntry = createPalmEntry( palmRec ); - syncEntry( pcEntry, backupEntry, palmEntry ); - // update the id just in case it changed - if ( palmRec ) - recID = palmRec->id(); - KPILOT_DELETE( palmRec ); - KPILOT_DELETE( palmEntry ); - } - - KPILOT_DELETE( pcEntry ); - KPILOT_DELETE( backupEntry ); - KPILOT_DELETE( backupRec ); - mSyncedIds.append( recID ); - - // done with the sync process, go on with the next one: - TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) ); -} - - - -void RecordConduit::slotDeletedRecord() -{ - FUNCTIONSETUP; - - PilotRecord *backupRec = fLocalDatabase->readRecordByIndex( mPalmIndex++ ); - if( !backupRec || isFirstSync() ) - { - KPILOT_DELETE(backupRec); - TQTimer::singleShot( 0, this, TQT_SLOT( slotDeleteUnsyncedPCRecords() ) ); - return; - } - - // already synced, so skip this record: - if ( mSyncedIds.contains( backupRec->id() ) ) - { - KPILOT_DELETE( backupRec ); - TQTimer::singleShot( 0, this, TQT_SLOT( slotDeletedRecord() ) ); - return; - } - - TQString uid = mEntryMap[ backupRec->id() ]; - PCEntry *pcEntry = mPCData->findByUid( uid ); - PilotRecord *palmRec = fDatabase->readRecordById( backupRec->id() ); - PilotAppCategory *backupEntry = 0L; - if (backupRec) - backupEntry = createPalmEntry( backupRec ); - PilotAppCategory*palmEntry=0L; - if (palmRec) - palmEntry = createPalmEntry( palmRec ); - - mSyncedIds.append( backupRec->id() ); - syncEntry( pcEntry, backupEntry, palmEntry ); - - KPILOT_DELETE( pcEntry ); - KPILOT_DELETE( palmEntry ); - KPILOT_DELETE( backupEntry ); - KPILOT_DELETE( palmRec ); - KPILOT_DELETE( backupRec ); - TQTimer::singleShot( 0, this, TQT_SLOT( slotDeletedRecord() ) ); -} - - - -void RecordConduit::slotDeleteUnsyncedPCRecords() -{ - FUNCTIONSETUP; - if ( getSyncDirection() == SyncAction::eCopyHHToPC ) - { - TQStringList uids; - RecordIDList::iterator it; - TQString uid; - for ( it = mSyncedIds.begin(); it != mSyncedIds.end(); ++it) - { - uid = mEntryMap[ *it ]; - if ( !uid.isEmpty() ) uids.append( uid ); - } - // TODO: Does this speed up anything? - // qHeapSort( uids ); - const TQStringList alluids( mPCData->uids() ); - TQStringList::ConstIterator uidit; - for ( uidit = alluids.constBegin(); uidit != alluids.constEnd(); ++uidit ) - { - if ( !uids.contains( *uidit ) ) - { -#ifdef DEBUG - DEBUGKPILOT << "Deleting PCEntry with uid " << (*uidit) << " from PC (is not on HH, and syncing with HH->PC direction)" << endl; -#endif - mPCData->removeEntry( *uidit ); - } - } - } - TQTimer::singleShot(0, this, TQT_SLOT(slotDeleteUnsyncedHHRecords())); -} - - - -void RecordConduit::slotDeleteUnsyncedHHRecords() -{ - FUNCTIONSETUP; - if ( getSyncDirection() == SyncAction::eCopyPCToHH ) - { - RecordIDList ids = fDatabase->idList(); - RecordIDList::iterator it; - for ( it = ids.begin(); it != ids.end(); ++it ) - { - if ( !mSyncedIds.contains(*it) ) - { -#ifdef DEBUG - DEBUGKPILOT << "Deleting record with ID " << *it << " from handheld (is not on PC, and syncing with PC->HH direction)" << endl; -#endif - fDatabase->deleteRecord(*it); - fLocalDatabase->deleteRecord(*it); - } - } - } - TQTimer::singleShot( 0, this, TQT_SLOT( slotCleanup() ) ); -} - - -void RecordConduit::slotCleanup() -{ - FUNCTIONSETUP; - - // Set the appInfoBlock, just in case the category labels changed - _setAppInfo(); - doPostSync(); - if(fDatabase) - { - fDatabase->resetSyncFlags(); - fDatabase->cleanup(); - } - if(fLocalDatabase) - { - fLocalDatabase->resetSyncFlags(); - fLocalDatabase->cleanup(); - } - KPILOT_DELETE( fDatabase ); - KPILOT_DELETE( fLocalDatabase ); - // TODO: do something if saving fails! - mPCData->saveData(); - mPCData->cleanup(); - emit syncDone(this); -} - - -/** Return the list of category names on the handheld - */ -const TQStringList RecordConduit::categories() const -{ - TQStringList cats; - for ( unsigned int j = 0; j < Pilot::CATEGORY_COUNT; j++ ) { - TQString catName( category( j ) ); - if ( !catName.isEmpty() ) cats << catName; - } - return cats; -} -int RecordConduit::findFlags() const -{ - return eqFlagsAlmostAll; -} - - -bool RecordConduit::isDeleted( const PilotAppCategory *palmEntry ) -{ - if ( !palmEntry ) - return true; - if ( palmEntry->isDeleted() && !palmEntry->isArchived() ) - return true; - if ( palmEntry->isArchived() ) - return !archiveDeleted(); - return false; -} -bool RecordConduit::isArchived( const PilotAppCategory *palmEntry ) -{ - if ( palmEntry && palmEntry->isArchived() ) - return archiveDeleted(); - else - return false; -} - - - - -/********************************************************************* - L O A D I N G T H E D A T A - *********************************************************************/ - - - -bool RecordConduit::_prepare() -{ - FUNCTIONSETUP; - - readConfig(); - mSyncedIds.clear(); - mPCData = initializePCData(); - - return mPCData && doPrepare(); -} - - -void RecordConduit::_getAppInfo() -{ - FUNCTIONSETUP; - // get the address application header information - unsigned char *buffer = new unsigned char[Pilot::MAX_APPINFO_SIZE]; - int appLen=fDatabase->readAppBlock(buffer, Pilot::MAX_APPINFO_SIZE); - - doUnpackAppInfo( buffer, appLen ); - delete[] buffer; - buffer = 0; -} - -void RecordConduit::_setAppInfo() -{ - FUNCTIONSETUP; - // get the address application header information - int appLen = 0; - unsigned char *buffer = doPackAppInfo( &appLen ); - if ( buffer ) - { if (fDatabase) - fDatabase->writeAppBlock( buffer, appLen ); - if (fLocalDatabase) - fLocalDatabase->writeAppBlock( buffer, appLen ); - delete[] buffer; - } -} - - -int RecordConduit::compareStr( const TQString & str1, const TQString & str2 ) -{ -// FUNCTIONSETUP; - if ( str1.isEmpty() && str2.isEmpty() ) - return 0; - else - return str1.compare( str2 ); -} - - -/** - * _getCat returns the id of the category from the given categories list. - * If the address has no categories on the PC, TQString() is returned. - * If the current category exists in the list of cats, it is returned - * Otherwise the first cat in the list that exists on the HH is returned - * If none of the categories exists on the palm, TQString() is returned - */ -TQString RecordConduit::getCatForHH( const TQStringList cats, const TQString curr ) const -{ - FUNCTIONSETUP; - if ( cats.size() < 1 ) - return TQString(); - if ( cats.contains( curr ) ) - return curr; - for ( TQStringList::ConstIterator it = cats.begin(); it != cats.end(); ++it) - { - for ( unsigned int j = 0; j < Pilot::CATEGORY_COUNT; j++ ) - { - TQString catnm( category( j ) ); - if ( !(*it).isEmpty() && ( (*it)==catnm ) ) - { - return catnm; - } - } - } - // If we have a free label, return the first possible cat - TQString lastCat( category( Pilot::CATEGORY_COUNT-1 ) ); - return ( lastCat.isEmpty() ) ? ( cats.first() ) : ( TQString() ); -} - -void RecordConduit::setCategory(PCEntry * pcEntry, TQString cat) -{ - if ( !cat.isEmpty() && cat!=category( 0 ) ) - pcEntry->insertCategory(cat); -} - - - - - - -/********************************************************************* - G E N E R A L S Y N C F U N C T I O N - These functions modify the Handheld and the addressbook - *********************************************************************/ - - - -bool RecordConduit::syncEntry( PCEntry *pcEntry, PilotAppCategory*backupEntry, - PilotAppCategory*palmEntry) -{ - FUNCTIONSETUP; - - if ( getSyncDirection() == SyncAction::eCopyPCToHH ) - { - if ( pcEntry->isEmpty() ) - { - return pcDeleteEntry( pcEntry, backupEntry, palmEntry ); - } - else - { - return pcCopyToPalm( pcEntry, backupEntry, palmEntry ); - } - } - - if ( getSyncDirection() == SyncAction::eCopyHHToPC ) - { - if (!palmEntry) - return pcDeleteEntry(pcEntry, backupEntry, palmEntry); - else - return palmCopyToPC(pcEntry, backupEntry, palmEntry); - } - - if ( !backupEntry || isFirstSync() ) - { - /* - Resolution matrix (0..does not exist, E..exists, D..deleted flag set, A..archived): - HH PC | Resolution - ------------------------------------------------------------ - 0 A | - - 0 E | PC -> HH, reset ID if not set correctly - D 0 | delete (error, should never occur!!!) - D E | CR (ERROR) - E/A 0 | HH -> PC - E/A E/A| merge/CR - */ - if ( !palmEntry && isArchived( pcEntry ) ) - { - return true; - } - else if ( !palmEntry && !pcEntry->isEmpty() ) - { - // PC->HH - bool res = pcCopyToPalm( pcEntry, 0L, 0L ); - return res; - } - else if ( !palmEntry && pcEntry->isEmpty() ) - { - // everything's empty -> ERROR - return false; - } - else if ( ( isDeleted( palmEntry ) || isArchived( palmEntry ) ) && pcEntry->isEmpty()) - { - if ( isArchived( palmEntry ) ) - return palmCopyToPC( pcEntry, 0L, palmEntry ); - else - // this happens if you add a record on the handheld and delete it again before you do the next sync - return pcDeleteEntry( pcEntry, 0L, palmEntry ); - } - else if ( ( isDeleted(palmEntry) || isArchived( palmEntry ) ) && !pcEntry->isEmpty() ) - { - // CR (ERROR) - return smartMergeEntry( pcEntry, 0L, palmEntry ); - } - else if ( pcEntry->isEmpty() ) - { - // HH->PC - return palmCopyToPC( pcEntry, 0L, palmEntry ); - } - else - { - // Conflict Resolution - return smartMergeEntry( pcEntry, 0L, palmEntry ); - } - } // !backupEntry - else - { - /* - Resolution matrix: - 1) if HH.(empty| (deleted &! archived) ) -> { if (PC==B) -> delete, else -> CR } - if HH.archived -> {if (PC==B) -> copyToPC, else -> CR } - if PC.empty -> { if (HH==B) -> delete, else -> CR } - if PC.archived -> {if (HH==B) -> delete on HH, else CR } - 2) if PC==HH -> { update B, update ID of PC if needed } - 3) if PC==B -> { HH!=PC, thus HH modified, so copy HH->PC } - if HH==B -> { PC!=HH, thus PC modified, so copy PC->HH } - 4) else: all three PCEntrys are different -> CR - */ - - if ( !palmEntry || isDeleted(palmEntry) ) - { - if ( _equal( backupEntry, pcEntry ) || pcEntry->isEmpty() ) - { - return pcDeleteEntry( pcEntry, backupEntry, 0L ); - } - else - { - return smartMergeEntry( pcEntry, backupEntry, 0L ); - } - } - else if ( pcEntry->isEmpty() ) - { - if (*palmEntry == *backupEntry) - { - return pcDeleteEntry( pcEntry, backupEntry, palmEntry ); - } - else - { - return smartMergeEntry( pcEntry, backupEntry, palmEntry ); - } - } - else if ( _equal( palmEntry, pcEntry ) ) - { - // update Backup, update ID of PC if neededd - return backupSaveEntry( palmEntry ); - } - else if ( _equal( backupEntry, pcEntry ) ) - { -#ifdef DEBUG - DEBUGKPILOT << "Flags: " << palmEntry->getAttrib() << ", isDeleted=" << - isDeleted( palmEntry ) << ", isArchived=" << isArchived( palmEntry ) - << endl; -#endif - if ( isDeleted( palmEntry ) ) - { - return pcDeleteEntry( pcEntry, backupEntry, palmEntry ); - } - else - { - return palmCopyToPC( pcEntry, backupEntry, palmEntry ); - } - } - else if ( *palmEntry == *backupEntry ) - { - return pcCopyToPalm( pcEntry, backupEntry, palmEntry ); - } - else - { - // CR, since all are different - return smartMergeEntry( pcEntry, backupEntry, palmEntry ); - } - } // backupEntry - return false; -} - -bool RecordConduit::pcCopyToPalm( PCEntry *pcEntry, PilotAppCategory *backupEntry, - PilotAppCategory*palmEntry ) -{ - FUNCTIONSETUP; - - if ( pcEntry->isEmpty() ) return false; - PilotAppCategory *hhEntry = palmEntry; - bool hhEntryCreated = false; - if ( !hhEntry ) - { - hhEntry = createPalmEntry( 0 ); - hhEntryCreated=true; - } - _copy( hhEntry, pcEntry ); -#ifdef DEBUG - DEBUGKPILOT << "palmEntry->id=" << hhEntry->id() << ", pcEntry.ID=" << - pcEntry->uid() << endl; -#endif - - if( palmSaveEntry( hhEntry, pcEntry ) ) - { -#ifdef DEBUG - DEBUGKPILOT << "Entry palmEntry->id=" << - hhEntry->id() << "saved to palm, now updating pcEntry->uid()=" << pcEntry->uid() << endl; -#endif - pcSaveEntry( pcEntry, backupEntry, hhEntry ); - } - if ( hhEntryCreated ) KPILOT_DELETE( hhEntry ); - return true; -} - - - - -bool RecordConduit::palmCopyToPC( PCEntry *pcEntry, PilotAppCategory *backupEntry, - PilotAppCategory *palmEntry ) -{ - FUNCTIONSETUP; - if ( !palmEntry ) - { - return false; - } - _copy( pcEntry, palmEntry ); - pcSaveEntry( pcEntry, backupEntry, palmEntry ); - backupSaveEntry( palmEntry ); - return true; -} - - - -/********************************************************************* - l o w - l e v e l f u n c t i o n s f o r - adding / removing palm/pc records - *********************************************************************/ - - - -bool RecordConduit::palmSaveEntry( PilotAppCategory *palmEntry, PCEntry *pcEntry ) -{ - FUNCTIONSETUP; - -#ifdef DEBUG - DEBUGKPILOT << "Saving to pilot " << palmEntry->id() << endl; -#endif - - PilotRecord *pilotRec = palmEntry->pack(); - recordid_t pilotId = fDatabase->writeRecord(pilotRec); -#ifdef DEBUG - DEBUGKPILOT << "PilotRec nach writeRecord (" << pilotId << - ": ID=" << pilotRec->id() << endl; -#endif - fLocalDatabase->writeRecord( pilotRec ); - KPILOT_DELETE( pilotRec ); - - // pilotId == 0 if using local db, so don't overwrite the valid id - if ( pilotId != 0 ) - { - palmEntry->setID( pilotId ); - if ( !mSyncedIds.contains( pilotId ) ) - { - mSyncedIds.append( pilotId ); - } - } - - recordid_t hhId( pcEntry->recid() ); - if ( hhId != pilotId ) - { - pcEntry->setRecid( pilotId ); - return true; - } - - return false; -} - - - -bool RecordConduit::backupSaveEntry( PilotAppCategory *backup ) -{ - FUNCTIONSETUP; - if ( !backup ) return false; - - -#ifdef DEBUG -// showPilotAppCategory( backup ); -#endif - PilotRecord *pilotRec = backup->pack(); - fLocalDatabase->writeRecord( pilotRec ); - KPILOT_DELETE( pilotRec ); - return true; -} - - - -bool RecordConduit::pcSaveEntry( PCEntry *pcEntry, PilotAppCategory *, - PilotAppCategory * ) -{ - FUNCTIONSETUP; - -#ifdef DEBUG - DEBUGKPILOT << "Before _savepcEntry, pcEntry->uid()=" << - pcEntry->uid() << endl; -#endif - if ( pcEntry->recid() != 0 ) - { - mEntryMap.insert( pcEntry->recid(), pcEntry->uid() ); - } - - mPCData->updateEntry( pcEntry ); - return true; -} - - - -bool RecordConduit::pcDeleteEntry( PCEntry *pcEntry, PilotAppCategory *backupEntry, - PilotAppCategory *palmEntry ) -{ - FUNCTIONSETUP; - - if ( palmEntry ) - { - if ( !mSyncedIds.contains( palmEntry->id() ) ) - { - mSyncedIds.append(palmEntry->id()); - } - palmEntry->makeDeleted(); - PilotRecord *pilotRec = palmEntry->pack(); - pilotRec->setDeleted(); - mPalmIndex--; - fDatabase->writeRecord( pilotRec ); - fLocalDatabase->writeRecord( pilotRec ); - mSyncedIds.append( pilotRec->id() ); - KPILOT_DELETE( pilotRec ); - } - else if ( backupEntry ) - { - if ( !mSyncedIds.contains( backupEntry->id() ) ) - { - mSyncedIds.append( backupEntry->id() ); - } - backupEntry->makeDeleted(); - PilotRecord *pilotRec = backupEntry->pack(); - pilotRec->setDeleted(); - mPalmIndex--; - fLocalDatabase->writeRecord( pilotRec ); - mSyncedIds.append( pilotRec->id() ); - KPILOT_DELETE( pilotRec ); - } - if ( !pcEntry->isEmpty() ) - { -#ifdef DEBUG - DEBUGKPILOT << fname << " removing " << pcEntry->uid() << endl; -#endif - mPCData->removeEntry( pcEntry ); - } - return true; -} - - - -/********************************************************************* - C O P Y R E C O R D S - *********************************************************************/ - - - - - -/********************************************************************* - C O N F L I C T R E S O L U T I O N a n d M E R G I N G - *********************************************************************/ - - - - -// TODO: right now entries are equal if both first/last name and organization are -// equal. This rules out two entries for the same person(e.g. real home and weekend home) -// or two persons with the same name where you don't know the organization.!!! -RecordConduit::PCEntry *RecordConduit::findMatch( PilotAppCategory *palmEntry ) const -{ - FUNCTIONSETUP; - if ( !palmEntry ) - return 0; - - // TODO: also search with the pilotID - // first, use the pilotID to UID map to find the appropriate record - if( !isFirstSync() && ( palmEntry->id() > 0) ) - { - TQString id( mEntryMap[palmEntry->id()] ); -#ifdef DEBUG - DEBUGKPILOT << fname << ": PilotRecord has id " << palmEntry->id() << ", mapped to " << id << endl; -#endif - if( !id.isEmpty() ) - { - PCEntry *res = mPCData->findByUid( id ); - if ( !res && !res->isEmpty() ) return res; - KPILOT_DELETE( res ); -#ifdef DEBUG - DEBUGKPILOT << fname << ": PilotRecord has id " << palmEntry->id() << - ", but could not be found on the PC side" << endl; -#endif - } - } - - for ( PCData::Iterator iter = mPCData->begin(); !mPCData->atEnd( iter ); ++iter ) - { - PCEntry *abEntry = *iter; - recordid_t rid( abEntry->recid() ); - if ( rid>0 ) - { - if ( rid == palmEntry->id() ) - return abEntry;// yes, we found it - // skip this PCEntry, as it has a different corresponding address on the handheld - //if ( mAllIds.contains( rid ) ) continue; - } - - if ( _equal( palmEntry, abEntry, eqFlagsAlmostAll ) ) - { - return abEntry; - } - KPILOT_DELETE( abEntry ); - } -#ifdef DEBUG - DEBUGKPILOT << fname << ": Could not find any entry matching Palm record with id " << TQString::number( palmEntry->id() ) << endl; -#endif - return 0; -} - -#endif - - - - -#include "recordConduit.moc" - diff --git a/lib/recordConduit.cpp b/lib/recordConduit.cpp new file mode 100644 index 0000000..7c92152 --- /dev/null +++ b/lib/recordConduit.cpp @@ -0,0 +1,1145 @@ +/* KPilot +** +** Copyright (C) 2004 by Reinhold Kainhofer +** Based on the addressbook conduit: +** Copyright (C) 2000,2001 by Dan Pilone +** Copyright (C) 2000 Gregory Stern +** Copyright (C) 2002-2003 by Reinhold Kainhofer +** +** This conduit is the base class for all record-based conduits. +** all the sync logic is included in this class, and all child classes +** just have to implement some specific copying and conflict resolution +** methods. +*/ + +/* +** 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 +#include + +#include "pilotAppCategory.h" +#include "pilotSerialDatabase.h" +#include "pilotLocalDatabase.h" +#include "recordConduit.h" + + +// Something to allow us to check what revision +// the modules are that make up a binary distribution. +// +// +extern "C" +{ +long version_record_conduit = Pilot::PLUGIN_API; +} + + +/* virtual */ bool RecordConduitBase::exec() +{ + FUNCTIONSETUP; + fState = Initialize; + + setFirstSync(false); + + bool retrieved = false; + if (!openDatabases( fDBName, &retrieved)) + { + emit logError(i18n("Unable to open the %1 database on the handheld.").arg( fDBName ) ); + return false; + } + if (retrieved) setFirstSync(true); + + if (isFirstSync()) fIDList=fDatabase->idList(); + else fIDList=fDatabase->modifiedIDList(); + fIDListIterator = fIDList.begin(); + + fTimer = new TQTimer(this); + connect(fTimer,TQT_SIGNAL(timeout()),this,TQT_SLOT(process())); + fTimer->start(0,false); // Fire as often as possible to prompt processing + return true; +} + +/* virtual */ void RecordConduitBase::process() +{ + FUNCTIONSETUP; + SyncProgress p = Error; + +#ifdef DEBUG + DEBUGKPILOT << fname << ": From state " << name(fState) << endl; +#endif + + switch(fState) + { + case Initialize : + p = loadPC(); + break; + case PalmToPC : + p = palmRecToPC(); + break; + case PCToPalm : + p = pcRecToPalm(); + break; + case Cleanup : + p = cleanup(); + break; + } + +#ifdef DEBUG + DEBUGKPILOT << fname << ": Step returned " << name(p) << endl; +#endif + + switch(p) + { + case Error : + fTimer->stop(); + delayDone(); + return; + case NotDone : + // Return so we get called again. + return; + case Done : + // Get on with it. + break; + } + +#ifdef DEBUG + DEBUGKPILOT << fname << ": Step is done, moving to next state." << endl; +#endif + + // Here the previous call was done. + switch(fState) + { + case Initialize : + switch (syncMode().mode()) + { + case SyncMode::eRestore : + case SyncMode::eCopyPCToHH : /* These two don't copy Palm records to the PC */ + fState = PCToPalm; + break; + default : + fState = PalmToPC; + } + break; + case PalmToPC : + switch (syncMode().mode()) + { + case SyncMode::eBackup : + case SyncMode::eCopyHHToPC : /* These modes don't copy PC records back */ + fState = Cleanup; + break; + default : + fState = PCToPalm; + } + break; + case PCToPalm : + fState = Cleanup; + break; + case Cleanup : + fTimer->stop(); + delayDone(); + // No change in state, timer stopped and we're done. + break; + } + +#ifdef DEBUG + DEBUGKPILOT << fname << ": Next state is " << name(fState) << endl; +#endif + +} + + +TQString RecordConduitBase::name(RecordConduitBase::SyncProgress s) +{ + switch(s) + { + case RecordConduitBase::NotDone: + return CSL1("NotDone"); + case RecordConduitBase::Done: + return CSL1("Done"); + case RecordConduitBase::Error: + return CSL1("Error"); + } +} + + +TQString RecordConduitBase::name(RecordConduitBase::States s) +{ + switch(s) + { + case RecordConduitBase::Initialize: + return CSL1("Initialize"); + case RecordConduitBase::PalmToPC: + return CSL1("Handheld-to-PC"); + case RecordConduitBase::PCToPalm: + return CSL1("PC-to-Handheld"); + case RecordConduitBase::Cleanup: + return CSL1("Cleanup"); + } +} + + +#if 0 +/** make that entry on the pc archived (i.e. deleted on the handheld, + * while present on the pc, but not synced to the handheld */ +bool RecordConduit::PCData::makeArchived( RecordConduit::PCEntry *pcEntry ) +{ + if ( pcEntry ) { + pcEntry->makeArchived(); + setChanged( true ); + return true; + } else return false; +} + + +/* Builds the map which links record ids to uid's of PCEntry. This is the slow implementation, + * that should always work. subclasses should reimplement it to speed things up. +*/ +bool RecordConduit::PCData::mapContactsToPilot( TQMap &idContactMap ) +{ + FUNCTIONSETUP; + + idContactMap.clear(); + + Iterator it = begin(); + PCEntry *ent; + while ( !atEnd( it ) ) { + ent = *it; + recordid_t id( ent->recid() ); + if ( id != 0 ) { + idContactMap.insert( id, ent->uid() ); + } + ++it; + } +#ifdef DEBUG + DEBUGKPILOT << fname << ": Loaded " << idContactMap.size() << + " Entries on the pc and mapped them to records on the handheld. " << endl; +#endif + return true; +} + + + +/********************************************************************* + C O N S T R U C T O R + *********************************************************************/ + + + +bool RecordConduit::mArchiveDeleted = false; + +RecordConduit::RecordConduit(TQString name, KPilotDeviceLink * o, const char *n, const TQStringList & a): + ConduitAction(o, n, a), + mPCData(0), mPalmIndex(0), + mEntryMap(), mSyncedIds(), mAllIds() +{ + FUNCTIONSETUP; + fConduitName = name; +} + + + +RecordConduit::~RecordConduit() +{ + if ( mPCData ) KPILOT_DELETE(mPCData); +} + + + + + + +/********************************************************************* + S Y N C S T R U C T U R E + *********************************************************************/ + + + +/* virtual */ bool RecordConduit::exec() +{ + FUNCTIONSETUP; + + if ( !_prepare() ) return false; + + fFirstSync = false; + // Database names probably in latin1. + if( !openDatabases( dbName(), &fFirstSync ) ) + { + emit logError(i18n("Unable to open the %1 database on the handheld.").arg( dbName() ) ); + return false; + } + _getAppInfo(); + if( !mPCData->loadData() ) + { + emit logError( i18n("Unable to open %1.").arg( mPCData->description() ) ); + return false; + } + // get the addresseMap which maps Pilot unique record(address) id's to + // a Abbrowser Addressee; allows for easy lookup and comparisons + if ( mPCData->isEmpty() ) + fFirstSync = true; + else + mPCData->mapContactsToPilot( mEntryMap ); + fFirstSync = fFirstSync || ( mPCData->isEmpty() ); + + // perform syncing from palm to abbrowser + // iterate through all records in palm pilot + mPalmIndex = 0; + +#ifdef DEBUG + DEBUGKPILOT << fname << ": fullsync=" << isFullSync() << ", firstSync=" << isFirstSync() << endl; + DEBUGKPILOT << fname << ": " + << "syncDirection=" << getSyncDirection() << ", " +// << "archive = " << AbbrowserSettings::archiveDeleted() + << endl; + DEBUGKPILOT << fname << ": conflictRes="<< getConflictResolution() << endl; +// DEBUGKPILOT << fname << ": PilotStreetHome=" << AbbrowserSettings::pilotStreet() << ", PilotFaxHOme" << AbbrowserSettings::pilotFax() << endl; +#endif + + if ( !isFirstSync() ) + mAllIds=fDatabase->idList(); + + /* Note: + if eCopyPCToHH or eCopyHHToPC, first sync everything, then lookup + those entries on the receiving side that are not yet syncced and delete + them. Use slotDeleteUnsyncedPCRecords and slotDeleteUnsyncedHHRecords + for this, and no longer purge the whole addressbook before the sync to + prevent data loss in case of connection loss. */ + + TQTimer::singleShot(0, this, TQT_SLOT(slotPalmRecToPC())); + + return true; +} + + + +void RecordConduit::slotPalmRecToPC() +{ + FUNCTIONSETUP; + PilotRecord *palmRec = 0L, *backupRec = 0L; + + if ( getSyncDirection() == SyncAction::eCopyPCToHH ) + { + mPCIter = mPCData->begin(); + TQTimer::singleShot(0, this, TQT_SLOT(slotPCRecToPalm())); + return; + } + + if ( isFullSync() ) + palmRec = fDatabase->readRecordByIndex( mPalmIndex++ ); + else + palmRec = dynamic_cast (fDatabase)->readNextModifiedRec(); + + if ( !palmRec ) + { + mPCIter = mPCData->begin(); + TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) ); + return; + } + + // already synced, so skip: + if ( mSyncedIds.contains( palmRec->id() ) ) + { + KPILOT_DELETE( palmRec ); + TQTimer::singleShot( 0, this, TQT_SLOT( slotPalmRecToPC() ) ); + return; + } + + backupRec = fLocalDatabase->readRecordById( palmRec->id() ); + PilotRecord *compareRec = backupRec ? backupRec : palmRec; + PilotAppCategory *compareEntry = createPalmEntry( compareRec ); + PCEntry *pcEntry = findMatch( compareEntry ); + KPILOT_DELETE( compareEntry ); + + PilotAppCategory *backupEntry=0L; + if ( backupRec ) + backupEntry = createPalmEntry( backupRec ); + PilotAppCategory *palmEntry=0L; + if ( palmRec ) + palmEntry = createPalmEntry( palmRec ); + + syncEntry( pcEntry, backupEntry, palmEntry ); + + mSyncedIds.append( palmRec->id() ); + + KPILOT_DELETE( pcEntry ); + KPILOT_DELETE( palmEntry ); + KPILOT_DELETE( backupEntry ); + KPILOT_DELETE( palmRec ); + KPILOT_DELETE( backupRec ); + + TQTimer::singleShot(0, this, TQT_SLOT(slotPalmRecToPC())); +} + + + +void RecordConduit::slotPCRecToPalm() +{ + FUNCTIONSETUP; + + if ( ( getSyncDirection()==SyncAction::eCopyHHToPC ) || + mPCData->atEnd( mPCIter ) ) + { + mPalmIndex = 0; + TQTimer::singleShot( 0, this, TQT_SLOT( slotDeletedRecord() ) ); + return; + } + + PilotRecord *backupRec=0L; + PCEntry *pcEntry = *mPCIter; + ++mPCIter; + + // If marked as archived, don't sync! + if ( isArchived( pcEntry ) ) + { +#ifdef DEBUG + DEBUGKPILOT << fname << ": address with id " << pcEntry->uid() << + " marked archived, so don't sync." << endl; +#endif + KPILOT_DELETE( pcEntry ); + TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) ); + return; + } + + recordid_t recID( pcEntry->recid() ); + if ( recID == 0 ) + { + // it's a new item(no record ID and not inserted by the Palm -> PC sync), so add it + syncEntry( pcEntry, 0L, 0L ); + KPILOT_DELETE( pcEntry ); + TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) ); + return; + } + + // look into the list of already synced record ids to see if the PCEntry hasn't already been synced + if ( mSyncedIds.contains( recID ) ) + { +#ifdef DEBUG + DEBUGKPILOT << ": address with id " << recID << " already synced." << endl; +#endif + KPILOT_DELETE( pcEntry ); + TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) ); + return; + } + + + backupRec = fLocalDatabase->readRecordById( recID ); + // only update if no backup record or the backup record is not equal to the PCEntry + + PilotAppCategory*backupEntry=0L; + if ( backupRec ) + backupEntry = createPalmEntry( backupRec ); + if( !backupRec || isFirstSync() || !_equal( backupEntry, pcEntry ) ) + { + PilotRecord *palmRec = fDatabase->readRecordById( recID ); + PilotAppCategory *palmEntry=0L; + if (palmRec) + palmEntry = createPalmEntry( palmRec ); + syncEntry( pcEntry, backupEntry, palmEntry ); + // update the id just in case it changed + if ( palmRec ) + recID = palmRec->id(); + KPILOT_DELETE( palmRec ); + KPILOT_DELETE( palmEntry ); + } + + KPILOT_DELETE( pcEntry ); + KPILOT_DELETE( backupEntry ); + KPILOT_DELETE( backupRec ); + mSyncedIds.append( recID ); + + // done with the sync process, go on with the next one: + TQTimer::singleShot( 0, this, TQT_SLOT( slotPCRecToPalm() ) ); +} + + + +void RecordConduit::slotDeletedRecord() +{ + FUNCTIONSETUP; + + PilotRecord *backupRec = fLocalDatabase->readRecordByIndex( mPalmIndex++ ); + if( !backupRec || isFirstSync() ) + { + KPILOT_DELETE(backupRec); + TQTimer::singleShot( 0, this, TQT_SLOT( slotDeleteUnsyncedPCRecords() ) ); + return; + } + + // already synced, so skip this record: + if ( mSyncedIds.contains( backupRec->id() ) ) + { + KPILOT_DELETE( backupRec ); + TQTimer::singleShot( 0, this, TQT_SLOT( slotDeletedRecord() ) ); + return; + } + + TQString uid = mEntryMap[ backupRec->id() ]; + PCEntry *pcEntry = mPCData->findByUid( uid ); + PilotRecord *palmRec = fDatabase->readRecordById( backupRec->id() ); + PilotAppCategory *backupEntry = 0L; + if (backupRec) + backupEntry = createPalmEntry( backupRec ); + PilotAppCategory*palmEntry=0L; + if (palmRec) + palmEntry = createPalmEntry( palmRec ); + + mSyncedIds.append( backupRec->id() ); + syncEntry( pcEntry, backupEntry, palmEntry ); + + KPILOT_DELETE( pcEntry ); + KPILOT_DELETE( palmEntry ); + KPILOT_DELETE( backupEntry ); + KPILOT_DELETE( palmRec ); + KPILOT_DELETE( backupRec ); + TQTimer::singleShot( 0, this, TQT_SLOT( slotDeletedRecord() ) ); +} + + + +void RecordConduit::slotDeleteUnsyncedPCRecords() +{ + FUNCTIONSETUP; + if ( getSyncDirection() == SyncAction::eCopyHHToPC ) + { + TQStringList uids; + RecordIDList::iterator it; + TQString uid; + for ( it = mSyncedIds.begin(); it != mSyncedIds.end(); ++it) + { + uid = mEntryMap[ *it ]; + if ( !uid.isEmpty() ) uids.append( uid ); + } + // TODO: Does this speed up anything? + // qHeapSort( uids ); + const TQStringList alluids( mPCData->uids() ); + TQStringList::ConstIterator uidit; + for ( uidit = alluids.constBegin(); uidit != alluids.constEnd(); ++uidit ) + { + if ( !uids.contains( *uidit ) ) + { +#ifdef DEBUG + DEBUGKPILOT << "Deleting PCEntry with uid " << (*uidit) << " from PC (is not on HH, and syncing with HH->PC direction)" << endl; +#endif + mPCData->removeEntry( *uidit ); + } + } + } + TQTimer::singleShot(0, this, TQT_SLOT(slotDeleteUnsyncedHHRecords())); +} + + + +void RecordConduit::slotDeleteUnsyncedHHRecords() +{ + FUNCTIONSETUP; + if ( getSyncDirection() == SyncAction::eCopyPCToHH ) + { + RecordIDList ids = fDatabase->idList(); + RecordIDList::iterator it; + for ( it = ids.begin(); it != ids.end(); ++it ) + { + if ( !mSyncedIds.contains(*it) ) + { +#ifdef DEBUG + DEBUGKPILOT << "Deleting record with ID " << *it << " from handheld (is not on PC, and syncing with PC->HH direction)" << endl; +#endif + fDatabase->deleteRecord(*it); + fLocalDatabase->deleteRecord(*it); + } + } + } + TQTimer::singleShot( 0, this, TQT_SLOT( slotCleanup() ) ); +} + + +void RecordConduit::slotCleanup() +{ + FUNCTIONSETUP; + + // Set the appInfoBlock, just in case the category labels changed + _setAppInfo(); + doPostSync(); + if(fDatabase) + { + fDatabase->resetSyncFlags(); + fDatabase->cleanup(); + } + if(fLocalDatabase) + { + fLocalDatabase->resetSyncFlags(); + fLocalDatabase->cleanup(); + } + KPILOT_DELETE( fDatabase ); + KPILOT_DELETE( fLocalDatabase ); + // TODO: do something if saving fails! + mPCData->saveData(); + mPCData->cleanup(); + emit syncDone(this); +} + + +/** Return the list of category names on the handheld + */ +const TQStringList RecordConduit::categories() const +{ + TQStringList cats; + for ( unsigned int j = 0; j < Pilot::CATEGORY_COUNT; j++ ) { + TQString catName( category( j ) ); + if ( !catName.isEmpty() ) cats << catName; + } + return cats; +} +int RecordConduit::findFlags() const +{ + return eqFlagsAlmostAll; +} + + +bool RecordConduit::isDeleted( const PilotAppCategory *palmEntry ) +{ + if ( !palmEntry ) + return true; + if ( palmEntry->isDeleted() && !palmEntry->isArchived() ) + return true; + if ( palmEntry->isArchived() ) + return !archiveDeleted(); + return false; +} +bool RecordConduit::isArchived( const PilotAppCategory *palmEntry ) +{ + if ( palmEntry && palmEntry->isArchived() ) + return archiveDeleted(); + else + return false; +} + + + + +/********************************************************************* + L O A D I N G T H E D A T A + *********************************************************************/ + + + +bool RecordConduit::_prepare() +{ + FUNCTIONSETUP; + + readConfig(); + mSyncedIds.clear(); + mPCData = initializePCData(); + + return mPCData && doPrepare(); +} + + +void RecordConduit::_getAppInfo() +{ + FUNCTIONSETUP; + // get the address application header information + unsigned char *buffer = new unsigned char[Pilot::MAX_APPINFO_SIZE]; + int appLen=fDatabase->readAppBlock(buffer, Pilot::MAX_APPINFO_SIZE); + + doUnpackAppInfo( buffer, appLen ); + delete[] buffer; + buffer = 0; +} + +void RecordConduit::_setAppInfo() +{ + FUNCTIONSETUP; + // get the address application header information + int appLen = 0; + unsigned char *buffer = doPackAppInfo( &appLen ); + if ( buffer ) + { if (fDatabase) + fDatabase->writeAppBlock( buffer, appLen ); + if (fLocalDatabase) + fLocalDatabase->writeAppBlock( buffer, appLen ); + delete[] buffer; + } +} + + +int RecordConduit::compareStr( const TQString & str1, const TQString & str2 ) +{ +// FUNCTIONSETUP; + if ( str1.isEmpty() && str2.isEmpty() ) + return 0; + else + return str1.compare( str2 ); +} + + +/** + * _getCat returns the id of the category from the given categories list. + * If the address has no categories on the PC, TQString() is returned. + * If the current category exists in the list of cats, it is returned + * Otherwise the first cat in the list that exists on the HH is returned + * If none of the categories exists on the palm, TQString() is returned + */ +TQString RecordConduit::getCatForHH( const TQStringList cats, const TQString curr ) const +{ + FUNCTIONSETUP; + if ( cats.size() < 1 ) + return TQString(); + if ( cats.contains( curr ) ) + return curr; + for ( TQStringList::ConstIterator it = cats.begin(); it != cats.end(); ++it) + { + for ( unsigned int j = 0; j < Pilot::CATEGORY_COUNT; j++ ) + { + TQString catnm( category( j ) ); + if ( !(*it).isEmpty() && ( (*it)==catnm ) ) + { + return catnm; + } + } + } + // If we have a free label, return the first possible cat + TQString lastCat( category( Pilot::CATEGORY_COUNT-1 ) ); + return ( lastCat.isEmpty() ) ? ( cats.first() ) : ( TQString() ); +} + +void RecordConduit::setCategory(PCEntry * pcEntry, TQString cat) +{ + if ( !cat.isEmpty() && cat!=category( 0 ) ) + pcEntry->insertCategory(cat); +} + + + + + + +/********************************************************************* + G E N E R A L S Y N C F U N C T I O N + These functions modify the Handheld and the addressbook + *********************************************************************/ + + + +bool RecordConduit::syncEntry( PCEntry *pcEntry, PilotAppCategory*backupEntry, + PilotAppCategory*palmEntry) +{ + FUNCTIONSETUP; + + if ( getSyncDirection() == SyncAction::eCopyPCToHH ) + { + if ( pcEntry->isEmpty() ) + { + return pcDeleteEntry( pcEntry, backupEntry, palmEntry ); + } + else + { + return pcCopyToPalm( pcEntry, backupEntry, palmEntry ); + } + } + + if ( getSyncDirection() == SyncAction::eCopyHHToPC ) + { + if (!palmEntry) + return pcDeleteEntry(pcEntry, backupEntry, palmEntry); + else + return palmCopyToPC(pcEntry, backupEntry, palmEntry); + } + + if ( !backupEntry || isFirstSync() ) + { + /* + Resolution matrix (0..does not exist, E..exists, D..deleted flag set, A..archived): + HH PC | Resolution + ------------------------------------------------------------ + 0 A | - + 0 E | PC -> HH, reset ID if not set correctly + D 0 | delete (error, should never occur!!!) + D E | CR (ERROR) + E/A 0 | HH -> PC + E/A E/A| merge/CR + */ + if ( !palmEntry && isArchived( pcEntry ) ) + { + return true; + } + else if ( !palmEntry && !pcEntry->isEmpty() ) + { + // PC->HH + bool res = pcCopyToPalm( pcEntry, 0L, 0L ); + return res; + } + else if ( !palmEntry && pcEntry->isEmpty() ) + { + // everything's empty -> ERROR + return false; + } + else if ( ( isDeleted( palmEntry ) || isArchived( palmEntry ) ) && pcEntry->isEmpty()) + { + if ( isArchived( palmEntry ) ) + return palmCopyToPC( pcEntry, 0L, palmEntry ); + else + // this happens if you add a record on the handheld and delete it again before you do the next sync + return pcDeleteEntry( pcEntry, 0L, palmEntry ); + } + else if ( ( isDeleted(palmEntry) || isArchived( palmEntry ) ) && !pcEntry->isEmpty() ) + { + // CR (ERROR) + return smartMergeEntry( pcEntry, 0L, palmEntry ); + } + else if ( pcEntry->isEmpty() ) + { + // HH->PC + return palmCopyToPC( pcEntry, 0L, palmEntry ); + } + else + { + // Conflict Resolution + return smartMergeEntry( pcEntry, 0L, palmEntry ); + } + } // !backupEntry + else + { + /* + Resolution matrix: + 1) if HH.(empty| (deleted &! archived) ) -> { if (PC==B) -> delete, else -> CR } + if HH.archived -> {if (PC==B) -> copyToPC, else -> CR } + if PC.empty -> { if (HH==B) -> delete, else -> CR } + if PC.archived -> {if (HH==B) -> delete on HH, else CR } + 2) if PC==HH -> { update B, update ID of PC if needed } + 3) if PC==B -> { HH!=PC, thus HH modified, so copy HH->PC } + if HH==B -> { PC!=HH, thus PC modified, so copy PC->HH } + 4) else: all three PCEntrys are different -> CR + */ + + if ( !palmEntry || isDeleted(palmEntry) ) + { + if ( _equal( backupEntry, pcEntry ) || pcEntry->isEmpty() ) + { + return pcDeleteEntry( pcEntry, backupEntry, 0L ); + } + else + { + return smartMergeEntry( pcEntry, backupEntry, 0L ); + } + } + else if ( pcEntry->isEmpty() ) + { + if (*palmEntry == *backupEntry) + { + return pcDeleteEntry( pcEntry, backupEntry, palmEntry ); + } + else + { + return smartMergeEntry( pcEntry, backupEntry, palmEntry ); + } + } + else if ( _equal( palmEntry, pcEntry ) ) + { + // update Backup, update ID of PC if neededd + return backupSaveEntry( palmEntry ); + } + else if ( _equal( backupEntry, pcEntry ) ) + { +#ifdef DEBUG + DEBUGKPILOT << "Flags: " << palmEntry->getAttrib() << ", isDeleted=" << + isDeleted( palmEntry ) << ", isArchived=" << isArchived( palmEntry ) + << endl; +#endif + if ( isDeleted( palmEntry ) ) + { + return pcDeleteEntry( pcEntry, backupEntry, palmEntry ); + } + else + { + return palmCopyToPC( pcEntry, backupEntry, palmEntry ); + } + } + else if ( *palmEntry == *backupEntry ) + { + return pcCopyToPalm( pcEntry, backupEntry, palmEntry ); + } + else + { + // CR, since all are different + return smartMergeEntry( pcEntry, backupEntry, palmEntry ); + } + } // backupEntry + return false; +} + +bool RecordConduit::pcCopyToPalm( PCEntry *pcEntry, PilotAppCategory *backupEntry, + PilotAppCategory*palmEntry ) +{ + FUNCTIONSETUP; + + if ( pcEntry->isEmpty() ) return false; + PilotAppCategory *hhEntry = palmEntry; + bool hhEntryCreated = false; + if ( !hhEntry ) + { + hhEntry = createPalmEntry( 0 ); + hhEntryCreated=true; + } + _copy( hhEntry, pcEntry ); +#ifdef DEBUG + DEBUGKPILOT << "palmEntry->id=" << hhEntry->id() << ", pcEntry.ID=" << + pcEntry->uid() << endl; +#endif + + if( palmSaveEntry( hhEntry, pcEntry ) ) + { +#ifdef DEBUG + DEBUGKPILOT << "Entry palmEntry->id=" << + hhEntry->id() << "saved to palm, now updating pcEntry->uid()=" << pcEntry->uid() << endl; +#endif + pcSaveEntry( pcEntry, backupEntry, hhEntry ); + } + if ( hhEntryCreated ) KPILOT_DELETE( hhEntry ); + return true; +} + + + + +bool RecordConduit::palmCopyToPC( PCEntry *pcEntry, PilotAppCategory *backupEntry, + PilotAppCategory *palmEntry ) +{ + FUNCTIONSETUP; + if ( !palmEntry ) + { + return false; + } + _copy( pcEntry, palmEntry ); + pcSaveEntry( pcEntry, backupEntry, palmEntry ); + backupSaveEntry( palmEntry ); + return true; +} + + + +/********************************************************************* + l o w - l e v e l f u n c t i o n s f o r + adding / removing palm/pc records + *********************************************************************/ + + + +bool RecordConduit::palmSaveEntry( PilotAppCategory *palmEntry, PCEntry *pcEntry ) +{ + FUNCTIONSETUP; + +#ifdef DEBUG + DEBUGKPILOT << "Saving to pilot " << palmEntry->id() << endl; +#endif + + PilotRecord *pilotRec = palmEntry->pack(); + recordid_t pilotId = fDatabase->writeRecord(pilotRec); +#ifdef DEBUG + DEBUGKPILOT << "PilotRec nach writeRecord (" << pilotId << + ": ID=" << pilotRec->id() << endl; +#endif + fLocalDatabase->writeRecord( pilotRec ); + KPILOT_DELETE( pilotRec ); + + // pilotId == 0 if using local db, so don't overwrite the valid id + if ( pilotId != 0 ) + { + palmEntry->setID( pilotId ); + if ( !mSyncedIds.contains( pilotId ) ) + { + mSyncedIds.append( pilotId ); + } + } + + recordid_t hhId( pcEntry->recid() ); + if ( hhId != pilotId ) + { + pcEntry->setRecid( pilotId ); + return true; + } + + return false; +} + + + +bool RecordConduit::backupSaveEntry( PilotAppCategory *backup ) +{ + FUNCTIONSETUP; + if ( !backup ) return false; + + +#ifdef DEBUG +// showPilotAppCategory( backup ); +#endif + PilotRecord *pilotRec = backup->pack(); + fLocalDatabase->writeRecord( pilotRec ); + KPILOT_DELETE( pilotRec ); + return true; +} + + + +bool RecordConduit::pcSaveEntry( PCEntry *pcEntry, PilotAppCategory *, + PilotAppCategory * ) +{ + FUNCTIONSETUP; + +#ifdef DEBUG + DEBUGKPILOT << "Before _savepcEntry, pcEntry->uid()=" << + pcEntry->uid() << endl; +#endif + if ( pcEntry->recid() != 0 ) + { + mEntryMap.insert( pcEntry->recid(), pcEntry->uid() ); + } + + mPCData->updateEntry( pcEntry ); + return true; +} + + + +bool RecordConduit::pcDeleteEntry( PCEntry *pcEntry, PilotAppCategory *backupEntry, + PilotAppCategory *palmEntry ) +{ + FUNCTIONSETUP; + + if ( palmEntry ) + { + if ( !mSyncedIds.contains( palmEntry->id() ) ) + { + mSyncedIds.append(palmEntry->id()); + } + palmEntry->makeDeleted(); + PilotRecord *pilotRec = palmEntry->pack(); + pilotRec->setDeleted(); + mPalmIndex--; + fDatabase->writeRecord( pilotRec ); + fLocalDatabase->writeRecord( pilotRec ); + mSyncedIds.append( pilotRec->id() ); + KPILOT_DELETE( pilotRec ); + } + else if ( backupEntry ) + { + if ( !mSyncedIds.contains( backupEntry->id() ) ) + { + mSyncedIds.append( backupEntry->id() ); + } + backupEntry->makeDeleted(); + PilotRecord *pilotRec = backupEntry->pack(); + pilotRec->setDeleted(); + mPalmIndex--; + fLocalDatabase->writeRecord( pilotRec ); + mSyncedIds.append( pilotRec->id() ); + KPILOT_DELETE( pilotRec ); + } + if ( !pcEntry->isEmpty() ) + { +#ifdef DEBUG + DEBUGKPILOT << fname << " removing " << pcEntry->uid() << endl; +#endif + mPCData->removeEntry( pcEntry ); + } + return true; +} + + + +/********************************************************************* + C O P Y R E C O R D S + *********************************************************************/ + + + + + +/********************************************************************* + C O N F L I C T R E S O L U T I O N a n d M E R G I N G + *********************************************************************/ + + + + +// TODO: right now entries are equal if both first/last name and organization are +// equal. This rules out two entries for the same person(e.g. real home and weekend home) +// or two persons with the same name where you don't know the organization.!!! +RecordConduit::PCEntry *RecordConduit::findMatch( PilotAppCategory *palmEntry ) const +{ + FUNCTIONSETUP; + if ( !palmEntry ) + return 0; + + // TODO: also search with the pilotID + // first, use the pilotID to UID map to find the appropriate record + if( !isFirstSync() && ( palmEntry->id() > 0) ) + { + TQString id( mEntryMap[palmEntry->id()] ); +#ifdef DEBUG + DEBUGKPILOT << fname << ": PilotRecord has id " << palmEntry->id() << ", mapped to " << id << endl; +#endif + if( !id.isEmpty() ) + { + PCEntry *res = mPCData->findByUid( id ); + if ( !res && !res->isEmpty() ) return res; + KPILOT_DELETE( res ); +#ifdef DEBUG + DEBUGKPILOT << fname << ": PilotRecord has id " << palmEntry->id() << + ", but could not be found on the PC side" << endl; +#endif + } + } + + for ( PCData::Iterator iter = mPCData->begin(); !mPCData->atEnd( iter ); ++iter ) + { + PCEntry *abEntry = *iter; + recordid_t rid( abEntry->recid() ); + if ( rid>0 ) + { + if ( rid == palmEntry->id() ) + return abEntry;// yes, we found it + // skip this PCEntry, as it has a different corresponding address on the handheld + //if ( mAllIds.contains( rid ) ) continue; + } + + if ( _equal( palmEntry, abEntry, eqFlagsAlmostAll ) ) + { + return abEntry; + } + KPILOT_DELETE( abEntry ); + } +#ifdef DEBUG + DEBUGKPILOT << fname << ": Could not find any entry matching Palm record with id " << TQString::number( palmEntry->id() ) << endl; +#endif + return 0; +} + +#endif + + + + +#include "recordConduit.moc" + diff --git a/lib/syncAction.cc b/lib/syncAction.cc deleted file mode 100644 index 65a7c7c..0000000 --- a/lib/syncAction.cc +++ /dev/null @@ -1,512 +0,0 @@ -/* KPilot -** -** Copyright (C) 1998-2001 by Dan Pilone -** Copyright (C) 2003-2004 Reinhold Kainhofer -** Copyright (C) 2001 by Waldo Bastian (code in questionYesNo) -** -*/ - -/* -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU Lesser General Public License as published by -** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. -** -** You should have received a copy of the GNU Lesser 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 - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "syncAction.moc" -#include "kpilotlibSettings.h" - -SyncAction::SyncAction(KPilotLink *p, - const char *name) : - TQObject(p, name), - fHandle(p), - fParent(0L) -{ - FUNCTIONSETUP; -} - -SyncAction::SyncAction(KPilotLink *p, - TQWidget * visibleparent, - const char *name) : - TQObject(p, name), - fHandle(p), - fParent(visibleparent) -{ - FUNCTIONSETUP; -} - -SyncAction::~SyncAction() -{ -} - -/* virtual */ TQString SyncAction::statusString() const -{ - FUNCTIONSETUP; - TQString s = CSL1("status="); - - s.append(TQString::number(status())); - return s; -} - -/* slot */ void SyncAction::execConduit() -{ - FUNCTIONSETUP; - - DEBUGKPILOT << fname << ": Exec " << name() << endl; - - bool r = this->exec(); - - DEBUGKPILOT << fname << ": Exec " << name() - << (r ? " is running" : " failed to start") << endl; - - if (!r) - { - emit logError(i18n("The conduit %1 could not be executed.") - .arg(TQString::fromLatin1(name()))); - delayDone(); - } -} - -/* slot */ void SyncAction::delayedDoneSlot() -{ - emit syncDone(this); -} - -bool SyncAction::delayDone() -{ - TQTimer::singleShot(0,this,TQT_SLOT(delayedDoneSlot())); - return true; -} - -static struct -{ - SyncAction::SyncMode::Mode mode; - const char *name; -} maps[] = -{ - { SyncAction::SyncMode::eHotSync, "--hotsync" }, - { SyncAction::SyncMode::eFullSync, "--full" }, - { SyncAction::SyncMode::eCopyPCToHH, "--copyPCToHH" }, - { SyncAction::SyncMode::eCopyHHToPC, "--copyHHToPC" }, - { SyncAction::SyncMode::eBackup, "--backup" }, - { SyncAction::SyncMode::eRestore, "--restore" }, - { SyncAction::SyncMode::eFullSync, "--fullsync" }, - { SyncAction::SyncMode::eHotSync, (const char *)0 } -} -; - -SyncAction::SyncMode::SyncMode(const TQStringList &args) : - fMode(eHotSync), - fTest(args.contains("--test")), - fLocal(args.contains("--local")) -{ - int i = 0; - while(maps[i].name) - { - if (args.contains(TQString::fromLatin1(maps[i].name))) - { - fMode = maps[i].mode; - break; - } - i++; - } - - if (!maps[i].name) - { - WARNINGKPILOT << "No mode set by arguments (" - << args.join(",") << ") defaulting to HotSync." << endl; - } -} - -SyncAction::SyncMode::SyncMode(Mode m, bool test, bool local) : - fMode(m), - fTest(test), - fLocal(local) -{ - if ( ((int)m<(int)eHotSync) || ((int)m>(int)eRestore) ) - { - WARNINGKPILOT << "Mode value " << (int)m << " is illegal" - ", defaulting to HotSync." << endl; - fMode = eHotSync; - } -} - -TQStringList SyncAction::SyncMode::list() const -{ - FUNCTIONSETUPL(3); - - TQStringList l; - int i=0; - - while(maps[i].name) - { - if ( fMode == maps[i].mode ) - { - l.append(TQString::fromLatin1(maps[i].name)); - break; - } - i++; - } - if ( !maps[i].name ) - { - WARNINGKPILOT << "Mode " << fMode << " does not have a name." << endl; - l.append(TQString::fromLatin1(maps[0].name)); - } - - if (isTest()) l.append(CSL1("--test")); - if (isLocal()) l.append(CSL1("--local")); - return l; -} - -/* static */ TQString SyncAction::SyncMode::name(SyncAction::SyncMode::Mode e) -{ - switch(e) - { - case eHotSync : return i18n("HotSync"); - case eFullSync : return i18n("Full Synchronization"); - case eCopyPCToHH : return i18n("Copy PC to Handheld"); - case eCopyHHToPC : return i18n("Copy Handheld to PC"); - case eBackup : return i18n("Backup"); - case eRestore : return i18n("Restore From Backup"); - } - return CSL1(""); -} - -TQString SyncAction::SyncMode::name() const -{ - TQString s = name(fMode); - if (isTest()) - { - - s.append(CSL1(" [%1]").arg(i18n("Test Sync"))); - } - if (isLocal()) - { - s.append(CSL1(" [%1]").arg(i18n("Local Sync"))); - } - return s; -} - -bool SyncAction::SyncMode::setMode(int mode) -{ - // Resets test and local flags too - fTest = fLocal = false; - - if ( (mode>0) && (mode<=eRestore) ) - { - fMode = (SyncAction::SyncMode::Mode) mode; - return true; - } - else - { - WARNINGKPILOT << "Bad sync mode " << mode << " requested." << endl ; - fMode = eHotSync; - return false; - } -} - -bool SyncAction::SyncMode::setMode(SyncAction::SyncMode::Mode m) -{ - int i=0; - while ( maps[i].name ) - { - if ( maps[i].mode == m ) - { - fMode = m; - return true; - } - i++; - } - - WARNINGKPILOT << "Bad sync mode " << m << " requested." << endl ; - fMode = eHotSync; - return false; -} - -void SyncAction::startTickle(unsigned timeout) -{ - FUNCTIONSETUP; - - if (!deviceLink()) - { - WARNINGKPILOT << "Trying to tickle without a device." << endl; - } - else - { - connect(deviceLink(),TQT_SIGNAL(timeout()),this,TQT_SIGNAL(timeout())); - deviceLink()->startTickle(timeout); - } -} - -void SyncAction::stopTickle() -{ - FUNCTIONSETUP; - if (!deviceLink()) - { - WARNINGKPILOT << "Trying to tickle without a device." << endl; - } - else - { - disconnect(deviceLink(),TQT_SIGNAL(timeout()),this,TQT_SIGNAL(timeout())); - deviceLink()->stopTickle(); - } -} - - -int SyncAction::questionYesNo(const TQString & text, - const TQString & caption, - const TQString & key, - unsigned timeout, - const TQString & yes, - const TQString &no ) -{ - FUNCTIONSETUP; - - bool checkboxReturn = false; - int r; - KMessageBox::ButtonCode result; - if (!key.isEmpty()) - { - if (!KMessageBox::shouldBeShownYesNo(key,result)) - { - return result; - } - } - - KDialogBase *dialog = - new KDialogBase(caption.isNull()? i18n("Question") : caption, - KDialogBase::Yes | KDialogBase::No, - KDialogBase::Yes, KDialogBase::No, - fParent, "questionYesNo", true, true, - yes.isEmpty() ? KStdGuiItem::yes() : yes, - no.isEmpty() ? KStdGuiItem::no() : no); - - if ( (timeout > 0) && ( deviceLink() ) ) - { - TQObject::connect(deviceLink(), TQT_SIGNAL(timeout()), - dialog, TQT_SLOT(slotCancel())); - startTickle(timeout); - } - -#if KDE_IS_VERSION(3,3,0) - r = (KMessageBox::ButtonCode) KMessageBox::createKMessageBox(dialog, - TQMessageBox::Question, - text, - TQStringList(), - (key.isEmpty() ? TQString() : i18n("&Do not ask again")), - &checkboxReturn, - 0); - -#else - // The following code is taken from KDialogBase.cc, - // part of the KDE 2.2 libraries. Copyright 2001 - // by Waldo Bastian. - // - // - TQVBox *topcontents = new TQVBox(dialog); - - topcontents->setSpacing(KDialog::spacingHint() * 2); - topcontents->setMargin(KDialog::marginHint() * 2); - - TQWidget *contents = new TQWidget(topcontents); - TQHBoxLayout *lay = new TQHBoxLayout(contents); - - lay->setSpacing(KDialog::spacingHint() * 2); - - lay->addStretch(1); - TQLabel *label1 = new TQLabel( contents); - label1->setPixmap(TQMessageBox::standardIcon(TQMessageBox::Information)); - lay->add( label1 ); - TQLabel *label2 = new TQLabel( text, contents); - label2->setMinimumSize(label2->sizeHint()); - lay->add(label2); - lay->addStretch(1); - - TQSize extraSize = TQSize(50, 30); - - TQCheckBox *checkbox = 0L; - if (!key.isEmpty()) - { - checkbox = new TQCheckBox(i18n("Do not ask again"),topcontents); - extraSize = TQSize(50,0); - } - - dialog->setMainWidget(topcontents); - dialog->enableButtonSeparator(false); - dialog->incInitialSize(extraSize); - - r = dialog->exec(); - if (checkbox) - { - checkboxReturn = checkbox->isChecked(); - } -#endif - - switch(r) - { - case KDialogBase::Yes : result=KMessageBox::Yes ; break; - case KDialogBase::No : result=KMessageBox::No; break; - case KDialogBase::Cancel : result=KMessageBox::Cancel; break; - default : break; - } - - stopTickle(); - - if (!key.isEmpty() && checkboxReturn) - { - KMessageBox::saveDontShowAgainYesNo(key,result); - } - - return result; -} - - -int SyncAction::questionYesNoCancel(const TQString & text, - const TQString & caption, - const TQString & key, - unsigned timeout, - const TQString &yes, - const TQString &no) -{ - FUNCTIONSETUP; - - bool checkboxReturn = false; - int r; - KMessageBox::ButtonCode result; - - if (!key.isEmpty()) - { - if (!KMessageBox::shouldBeShownYesNo(key,result)) - { - if (result != KMessageBox::Cancel) - { - return result; - } - } - } - - KDialogBase *dialog = - new KDialogBase(caption.isNull()? i18n("Question") : caption, - KDialogBase::Yes | KDialogBase::No | KDialogBase::Cancel, - KDialogBase::Yes, KDialogBase::Cancel, - fParent, "questionYesNoCancel", true, true, - (yes.isEmpty() ? KStdGuiItem::yes() : yes), - (no.isEmpty() ? KStdGuiItem::no() : no), - KStdGuiItem::cancel()); - - if ( (timeout > 0) && (deviceLink()) ) - { - TQObject::connect(deviceLink(), TQT_SIGNAL(timeout()), - dialog, TQT_SLOT(slotCancel())); - startTickle(timeout); - } - -#if KDE_IS_VERSION(3,3,0) - r = KMessageBox::createKMessageBox(dialog, - TQMessageBox::Question, - text, - TQStringList(), - (key.isEmpty() ? TQString() : i18n("&Do not ask again")), - &checkboxReturn, - 0); -#else - // The following code is taken from KDialogBase.cc, - // part of the KDE 2.2 libraries. Copyright 2001 - // by Waldo Bastian. - // - // - TQVBox *topcontents = new TQVBox(dialog); - - topcontents->setSpacing(KDialog::spacingHint() * 2); - topcontents->setMargin(KDialog::marginHint() * 2); - - TQWidget *contents = new TQWidget(topcontents); - TQHBoxLayout *lay = new TQHBoxLayout(contents); - - lay->setSpacing(KDialog::spacingHint() * 2); - - lay->addStretch(1); - TQLabel *label1 = new TQLabel( contents); - label1->setPixmap(TQMessageBox::standardIcon(TQMessageBox::Information)); - lay->add( label1 ); - TQLabel *label2 = new TQLabel( text, contents); - label2->setMinimumSize(label2->sizeHint()); - lay->add(label2); - lay->addStretch(1); - - TQSize extraSize = TQSize(50, 30); - - TQCheckBox *checkbox = 0L; - if (!key.isEmpty()) - { - checkbox = new TQCheckBox(i18n("Do not ask again"),topcontents); - extraSize = TQSize(50,0); - } - - dialog->setMainWidget(topcontents); - dialog->enableButtonSeparator(false); - dialog->incInitialSize(extraSize); - - r = dialog->exec(); - if (checkbox) - { - checkboxReturn = checkbox->isChecked(); - } -#endif - - switch(r) - { - case KDialogBase::Yes : result=KMessageBox::Yes ; break; - case KDialogBase::No : result=KMessageBox::No; break; - case KDialogBase::Cancel : result=KMessageBox::Cancel; break; - default : break; - } - stopTickle(); - - if (!key.isEmpty() && checkboxReturn) - { - KMessageBox::saveDontShowAgainYesNo(key,result); - } - - return result; -} - diff --git a/lib/syncAction.cpp b/lib/syncAction.cpp new file mode 100644 index 0000000..30951ad --- /dev/null +++ b/lib/syncAction.cpp @@ -0,0 +1,512 @@ +/* KPilot +** +** Copyright (C) 1998-2001 by Dan Pilone +** Copyright (C) 2003-2004 Reinhold Kainhofer +** Copyright (C) 2001 by Waldo Bastian (code in questionYesNo) +** +*/ + +/* +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser 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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "syncAction.moc" +#include "kpilotlibSettings.h" + +SyncAction::SyncAction(KPilotLink *p, + const char *name) : + TQObject(p, name), + fHandle(p), + fParent(0L) +{ + FUNCTIONSETUP; +} + +SyncAction::SyncAction(KPilotLink *p, + TQWidget * visibleparent, + const char *name) : + TQObject(p, name), + fHandle(p), + fParent(visibleparent) +{ + FUNCTIONSETUP; +} + +SyncAction::~SyncAction() +{ +} + +/* virtual */ TQString SyncAction::statusString() const +{ + FUNCTIONSETUP; + TQString s = CSL1("status="); + + s.append(TQString::number(status())); + return s; +} + +/* slot */ void SyncAction::execConduit() +{ + FUNCTIONSETUP; + + DEBUGKPILOT << fname << ": Exec " << name() << endl; + + bool r = this->exec(); + + DEBUGKPILOT << fname << ": Exec " << name() + << (r ? " is running" : " failed to start") << endl; + + if (!r) + { + emit logError(i18n("The conduit %1 could not be executed.") + .arg(TQString::fromLatin1(name()))); + delayDone(); + } +} + +/* slot */ void SyncAction::delayedDoneSlot() +{ + emit syncDone(this); +} + +bool SyncAction::delayDone() +{ + TQTimer::singleShot(0,this,TQT_SLOT(delayedDoneSlot())); + return true; +} + +static struct +{ + SyncAction::SyncMode::Mode mode; + const char *name; +} maps[] = +{ + { SyncAction::SyncMode::eHotSync, "--hotsync" }, + { SyncAction::SyncMode::eFullSync, "--full" }, + { SyncAction::SyncMode::eCopyPCToHH, "--copyPCToHH" }, + { SyncAction::SyncMode::eCopyHHToPC, "--copyHHToPC" }, + { SyncAction::SyncMode::eBackup, "--backup" }, + { SyncAction::SyncMode::eRestore, "--restore" }, + { SyncAction::SyncMode::eFullSync, "--fullsync" }, + { SyncAction::SyncMode::eHotSync, (const char *)0 } +} +; + +SyncAction::SyncMode::SyncMode(const TQStringList &args) : + fMode(eHotSync), + fTest(args.contains("--test")), + fLocal(args.contains("--local")) +{ + int i = 0; + while(maps[i].name) + { + if (args.contains(TQString::fromLatin1(maps[i].name))) + { + fMode = maps[i].mode; + break; + } + i++; + } + + if (!maps[i].name) + { + WARNINGKPILOT << "No mode set by arguments (" + << args.join(",") << ") defaulting to HotSync." << endl; + } +} + +SyncAction::SyncMode::SyncMode(Mode m, bool test, bool local) : + fMode(m), + fTest(test), + fLocal(local) +{ + if ( ((int)m<(int)eHotSync) || ((int)m>(int)eRestore) ) + { + WARNINGKPILOT << "Mode value " << (int)m << " is illegal" + ", defaulting to HotSync." << endl; + fMode = eHotSync; + } +} + +TQStringList SyncAction::SyncMode::list() const +{ + FUNCTIONSETUPL(3); + + TQStringList l; + int i=0; + + while(maps[i].name) + { + if ( fMode == maps[i].mode ) + { + l.append(TQString::fromLatin1(maps[i].name)); + break; + } + i++; + } + if ( !maps[i].name ) + { + WARNINGKPILOT << "Mode " << fMode << " does not have a name." << endl; + l.append(TQString::fromLatin1(maps[0].name)); + } + + if (isTest()) l.append(CSL1("--test")); + if (isLocal()) l.append(CSL1("--local")); + return l; +} + +/* static */ TQString SyncAction::SyncMode::name(SyncAction::SyncMode::Mode e) +{ + switch(e) + { + case eHotSync : return i18n("HotSync"); + case eFullSync : return i18n("Full Synchronization"); + case eCopyPCToHH : return i18n("Copy PC to Handheld"); + case eCopyHHToPC : return i18n("Copy Handheld to PC"); + case eBackup : return i18n("Backup"); + case eRestore : return i18n("Restore From Backup"); + } + return CSL1(""); +} + +TQString SyncAction::SyncMode::name() const +{ + TQString s = name(fMode); + if (isTest()) + { + + s.append(CSL1(" [%1]").arg(i18n("Test Sync"))); + } + if (isLocal()) + { + s.append(CSL1(" [%1]").arg(i18n("Local Sync"))); + } + return s; +} + +bool SyncAction::SyncMode::setMode(int mode) +{ + // Resets test and local flags too + fTest = fLocal = false; + + if ( (mode>0) && (mode<=eRestore) ) + { + fMode = (SyncAction::SyncMode::Mode) mode; + return true; + } + else + { + WARNINGKPILOT << "Bad sync mode " << mode << " requested." << endl ; + fMode = eHotSync; + return false; + } +} + +bool SyncAction::SyncMode::setMode(SyncAction::SyncMode::Mode m) +{ + int i=0; + while ( maps[i].name ) + { + if ( maps[i].mode == m ) + { + fMode = m; + return true; + } + i++; + } + + WARNINGKPILOT << "Bad sync mode " << m << " requested." << endl ; + fMode = eHotSync; + return false; +} + +void SyncAction::startTickle(unsigned timeout) +{ + FUNCTIONSETUP; + + if (!deviceLink()) + { + WARNINGKPILOT << "Trying to tickle without a device." << endl; + } + else + { + connect(deviceLink(),TQT_SIGNAL(timeout()),this,TQT_SIGNAL(timeout())); + deviceLink()->startTickle(timeout); + } +} + +void SyncAction::stopTickle() +{ + FUNCTIONSETUP; + if (!deviceLink()) + { + WARNINGKPILOT << "Trying to tickle without a device." << endl; + } + else + { + disconnect(deviceLink(),TQT_SIGNAL(timeout()),this,TQT_SIGNAL(timeout())); + deviceLink()->stopTickle(); + } +} + + +int SyncAction::questionYesNo(const TQString & text, + const TQString & caption, + const TQString & key, + unsigned timeout, + const TQString & yes, + const TQString &no ) +{ + FUNCTIONSETUP; + + bool checkboxReturn = false; + int r; + KMessageBox::ButtonCode result; + if (!key.isEmpty()) + { + if (!KMessageBox::shouldBeShownYesNo(key,result)) + { + return result; + } + } + + KDialogBase *dialog = + new KDialogBase(caption.isNull()? i18n("Question") : caption, + KDialogBase::Yes | KDialogBase::No, + KDialogBase::Yes, KDialogBase::No, + fParent, "questionYesNo", true, true, + yes.isEmpty() ? KStdGuiItem::yes() : yes, + no.isEmpty() ? KStdGuiItem::no() : no); + + if ( (timeout > 0) && ( deviceLink() ) ) + { + TQObject::connect(deviceLink(), TQT_SIGNAL(timeout()), + dialog, TQT_SLOT(slotCancel())); + startTickle(timeout); + } + +#if KDE_IS_VERSION(3,3,0) + r = (KMessageBox::ButtonCode) KMessageBox::createKMessageBox(dialog, + TQMessageBox::Question, + text, + TQStringList(), + (key.isEmpty() ? TQString() : i18n("&Do not ask again")), + &checkboxReturn, + 0); + +#else + // The following code is taken from KDialogBase.cpp, + // part of the KDE 2.2 libraries. Copyright 2001 + // by Waldo Bastian. + // + // + TQVBox *topcontents = new TQVBox(dialog); + + topcontents->setSpacing(KDialog::spacingHint() * 2); + topcontents->setMargin(KDialog::marginHint() * 2); + + TQWidget *contents = new TQWidget(topcontents); + TQHBoxLayout *lay = new TQHBoxLayout(contents); + + lay->setSpacing(KDialog::spacingHint() * 2); + + lay->addStretch(1); + TQLabel *label1 = new TQLabel( contents); + label1->setPixmap(TQMessageBox::standardIcon(TQMessageBox::Information)); + lay->add( label1 ); + TQLabel *label2 = new TQLabel( text, contents); + label2->setMinimumSize(label2->sizeHint()); + lay->add(label2); + lay->addStretch(1); + + TQSize extraSize = TQSize(50, 30); + + TQCheckBox *checkbox = 0L; + if (!key.isEmpty()) + { + checkbox = new TQCheckBox(i18n("Do not ask again"),topcontents); + extraSize = TQSize(50,0); + } + + dialog->setMainWidget(topcontents); + dialog->enableButtonSeparator(false); + dialog->incInitialSize(extraSize); + + r = dialog->exec(); + if (checkbox) + { + checkboxReturn = checkbox->isChecked(); + } +#endif + + switch(r) + { + case KDialogBase::Yes : result=KMessageBox::Yes ; break; + case KDialogBase::No : result=KMessageBox::No; break; + case KDialogBase::Cancel : result=KMessageBox::Cancel; break; + default : break; + } + + stopTickle(); + + if (!key.isEmpty() && checkboxReturn) + { + KMessageBox::saveDontShowAgainYesNo(key,result); + } + + return result; +} + + +int SyncAction::questionYesNoCancel(const TQString & text, + const TQString & caption, + const TQString & key, + unsigned timeout, + const TQString &yes, + const TQString &no) +{ + FUNCTIONSETUP; + + bool checkboxReturn = false; + int r; + KMessageBox::ButtonCode result; + + if (!key.isEmpty()) + { + if (!KMessageBox::shouldBeShownYesNo(key,result)) + { + if (result != KMessageBox::Cancel) + { + return result; + } + } + } + + KDialogBase *dialog = + new KDialogBase(caption.isNull()? i18n("Question") : caption, + KDialogBase::Yes | KDialogBase::No | KDialogBase::Cancel, + KDialogBase::Yes, KDialogBase::Cancel, + fParent, "questionYesNoCancel", true, true, + (yes.isEmpty() ? KStdGuiItem::yes() : yes), + (no.isEmpty() ? KStdGuiItem::no() : no), + KStdGuiItem::cancel()); + + if ( (timeout > 0) && (deviceLink()) ) + { + TQObject::connect(deviceLink(), TQT_SIGNAL(timeout()), + dialog, TQT_SLOT(slotCancel())); + startTickle(timeout); + } + +#if KDE_IS_VERSION(3,3,0) + r = KMessageBox::createKMessageBox(dialog, + TQMessageBox::Question, + text, + TQStringList(), + (key.isEmpty() ? TQString() : i18n("&Do not ask again")), + &checkboxReturn, + 0); +#else + // The following code is taken from KDialogBase.cpp, + // part of the KDE 2.2 libraries. Copyright 2001 + // by Waldo Bastian. + // + // + TQVBox *topcontents = new TQVBox(dialog); + + topcontents->setSpacing(KDialog::spacingHint() * 2); + topcontents->setMargin(KDialog::marginHint() * 2); + + TQWidget *contents = new TQWidget(topcontents); + TQHBoxLayout *lay = new TQHBoxLayout(contents); + + lay->setSpacing(KDialog::spacingHint() * 2); + + lay->addStretch(1); + TQLabel *label1 = new TQLabel( contents); + label1->setPixmap(TQMessageBox::standardIcon(TQMessageBox::Information)); + lay->add( label1 ); + TQLabel *label2 = new TQLabel( text, contents); + label2->setMinimumSize(label2->sizeHint()); + lay->add(label2); + lay->addStretch(1); + + TQSize extraSize = TQSize(50, 30); + + TQCheckBox *checkbox = 0L; + if (!key.isEmpty()) + { + checkbox = new TQCheckBox(i18n("Do not ask again"),topcontents); + extraSize = TQSize(50,0); + } + + dialog->setMainWidget(topcontents); + dialog->enableButtonSeparator(false); + dialog->incInitialSize(extraSize); + + r = dialog->exec(); + if (checkbox) + { + checkboxReturn = checkbox->isChecked(); + } +#endif + + switch(r) + { + case KDialogBase::Yes : result=KMessageBox::Yes ; break; + case KDialogBase::No : result=KMessageBox::No; break; + case KDialogBase::Cancel : result=KMessageBox::Cancel; break; + default : break; + } + stopTickle(); + + if (!key.isEmpty() && checkboxReturn) + { + KMessageBox::saveDontShowAgainYesNo(key,result); + } + + return result; +} + -- cgit v1.2.1