summaryrefslogtreecommitdiffstats
path: root/kpilot/conduits/memofileconduit/memofile-conduit.cc
diff options
context:
space:
mode:
Diffstat (limited to 'kpilot/conduits/memofileconduit/memofile-conduit.cc')
-rw-r--r--kpilot/conduits/memofileconduit/memofile-conduit.cc567
1 files changed, 567 insertions, 0 deletions
diff --git a/kpilot/conduits/memofileconduit/memofile-conduit.cc b/kpilot/conduits/memofileconduit/memofile-conduit.cc
new file mode 100644
index 000000000..1dc5fe386
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile-conduit.cc
@@ -0,0 +1,567 @@
+/* memofile-conduit.cc KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+**
+** This file does the actual conduit work.
+*/
+
+/*
+** 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"
+
+// Only include what we really need:
+// First UNIX system stuff, then std C++,
+// then Qt, then KDE, then local includes.
+//
+//
+
+#include <time.h> // required by pilot-link includes
+
+#include <pi-memo.h>
+
+#include "pilotMemo.h"
+
+#include <qfile.h>
+#include <qdir.h>
+#include <qtextcodec.h>
+
+#include <kconfig.h>
+#include <kdebug.h>
+
+#include "pilotRecord.h"
+#include "pilotSerialDatabase.h"
+#include "memofile-factory.h"
+#include "memofile-conduit.h"
+#include "memofileSettings.h"
+
+
+/**
+ * Our workhorse. This is the main driver for the conduit.
+ */
+MemofileConduit::MemofileConduit(KPilotLink *d,
+ const char *n,
+ const QStringList &l) :
+ ConduitAction(d,n,l),
+ _DEFAULT_MEMODIR(QDir::homeDirPath() + CSL1("/MyMemos")),
+ fMemoAppInfo(0L),
+ _memofiles(0L)
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("Memofile");
+ fMemoList.setAutoDelete(true);
+}
+
+MemofileConduit::~MemofileConduit()
+{
+ FUNCTIONSETUP;
+ KPILOT_DELETE(_memofiles);
+}
+
+/* virtual */ bool MemofileConduit::exec()
+{
+ FUNCTIONSETUP;
+
+ setFirstSync( false );
+ // try new format first...
+ // DEBUGKPILOT << fname << ": trying new format database first." << endl;
+ bool _open = false;
+ /*
+ _open = openDatabases(CSL1("MemosDB-PMem"));
+ if(!_open) {
+ DEBUGKPILOT << fname << ": unable to open new format database. trying old one." << endl;
+ */
+ _open = openDatabases(CSL1("MemoDB"));
+ /*
+ } else {
+ DEBUGKPILOT << fname << ": able to open new format database." << endl;
+ }
+ */
+
+ if(!_open) {
+ emit logError(i18n("Unable to open the memo databases on the handheld."));
+ DEBUGKPILOT << fname << ": unable to open new or old format database." << endl;
+ return false;
+ }
+
+ readConfig();
+
+ if (! initializeFromPilot()) {
+ emit logError(i18n("Cannot initialize from pilot."));
+ return false;
+ }
+
+ _memofiles = new Memofiles(fCategories, *fMemoAppInfo,
+ _memo_directory, *fCtrHH);
+ if (! _memofiles || ! _memofiles->isReady()) {
+ emit logError(i18n("Cannot initialize the memo files from disk."));
+ return false;
+ }
+
+ fCtrPC->setStartCount(_memofiles->count());
+
+ setFirstSync( _memofiles->isFirstSync() );
+ addSyncLogEntry(i18n(" Syncing with %1.").arg(_memo_directory));
+
+ if ( (syncMode() == SyncAction::SyncMode::eCopyHHToPC) || _memofiles->isFirstSync() ) {
+ addSyncLogEntry(i18n(" Copying Pilot to PC..."));
+ DEBUGKPILOT << fname << ": copying Pilot to PC." << endl;
+ copyHHToPC();
+ } else if ( syncMode() == SyncAction::SyncMode::eCopyPCToHH ) {
+ DEBUGKPILOT << fname << ": copying PC to Pilot." << endl;
+ addSyncLogEntry(i18n(" Copying PC to Pilot..."));
+ copyPCToHH();
+ } else {
+ DEBUGKPILOT << fname << ": doing regular sync." << endl;
+ addSyncLogEntry(i18n(" Doing regular sync..."));
+ sync();
+ }
+
+ cleanup();
+
+ return delayDone();
+}
+
+bool MemofileConduit::readConfig()
+{
+ FUNCTIONSETUP;
+
+ QString dir(MemofileConduitSettings::directory());
+ if (dir.isEmpty()) {
+ dir = _DEFAULT_MEMODIR;
+
+ DEBUGKPILOT << fname
+ << ": no directory given to us. defaulting to: ["
+ << _DEFAULT_MEMODIR
+ << "]" << endl;
+ }
+
+ _memo_directory = dir;
+ _sync_private = MemofileConduitSettings::syncPrivate();
+
+
+ DEBUGKPILOT << fname
+ << ": Settings... "
+ << " directory: [" << _memo_directory
+ << "], first sync: [" << isFirstSync()
+ << "], sync private: [" << _sync_private
+ << "]" << endl;
+
+ return true;
+
+}
+
+bool MemofileConduit::setAppInfo()
+{
+ FUNCTIONSETUP;
+
+ // reset our category mapping from the filesystem
+ MemoCategoryMap map = _memofiles->readCategoryMetadata();
+
+ if (map.count() <=0) {
+ DEBUGKPILOT << fname
+ << ": category metadata map is empty, nothing to do." << endl;
+ return true;
+ }
+
+ fCategories = map;
+
+ for (unsigned int i = 0; i < Pilot::CATEGORY_COUNT; i++)
+ {
+ if (fCategories.contains(i)) {
+ fMemoAppInfo->setCategoryName(i,fCategories[i]);
+ }
+ }
+
+ if (fDatabase)
+ {
+ fMemoAppInfo->writeTo(fDatabase);
+ }
+ if (fLocalDatabase)
+ {
+ fMemoAppInfo->writeTo(fLocalDatabase);
+ }
+
+ return true;
+}
+
+bool MemofileConduit::getAppInfo()
+{
+ FUNCTIONSETUP;
+
+ KPILOT_DELETE(fMemoAppInfo);
+ fMemoAppInfo = new PilotMemoInfo(fDatabase);
+ fMemoAppInfo->dump();
+ return true;
+}
+
+
+/**
+ * Methods related to getting set up from the Pilot.
+ */
+
+bool MemofileConduit::initializeFromPilot()
+{
+
+ if (!getAppInfo()) return false;
+
+ if (!loadPilotCategories()) return false;
+
+ return true;
+}
+
+bool MemofileConduit::loadPilotCategories()
+{
+ FUNCTIONSETUP;
+
+ fCategories.clear();
+
+ QString _category_name;
+ int _category_id=0;
+ int _category_num=0;
+
+ for (unsigned int i = 0; i < Pilot::CATEGORY_COUNT; i++)
+ {
+ _category_name = fMemoAppInfo->categoryName(i);
+ if (!_category_name.isEmpty())
+ {
+ _category_name = Memofiles::sanitizeName( _category_name );
+ _category_id = fMemoAppInfo->categoryInfo()->ID[i];
+ _category_num = i;
+ fCategories[_category_num] = _category_name;
+
+ DEBUGKPILOT << fname
+ << ": Category #"
+ << _category_num
+ << " has ID "
+ << _category_id
+ << " and name "
+ <<_category_name << endl;
+ }
+ }
+ return true;
+}
+
+/**
+ * Read all memos in from Pilot.
+ */
+void MemofileConduit::getAllFromPilot()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname
+ << ": Database has " << fDatabase->recordCount()
+ << " records." << endl;
+
+ fMemoList.clear();
+
+ int currentRecord = 0;
+ PilotRecord *pilotRec;
+ PilotMemo *memo = 0;
+
+ while ((pilotRec = fDatabase->readRecordByIndex(currentRecord)) != NULL) {
+ if ((!pilotRec->isSecret()) || _sync_private) {
+ memo = new PilotMemo(pilotRec);
+ fMemoList.append(memo);
+
+ DEBUGKPILOT << fname
+ << ": Added memo: ["
+ << currentRecord
+ << "], id: ["
+ << memo->id()
+ << "], category: ["
+ << fCategories[memo->category()]
+ << "], title: ["
+ << memo->getTitle()
+ << "]" << endl;
+ } else {
+ DEBUGKPILOT << fname
+ << ": Skipped secret record: ["
+ << currentRecord
+ << "], title: ["
+ << memo->getTitle()
+ << "]" << endl;
+ }
+
+ KPILOT_DELETE(pilotRec);
+
+ currentRecord++;
+ }
+
+ DEBUGKPILOT << fname
+ << ": read: [" << fMemoList.count()
+ << "] records from palm." << endl;
+}
+
+/**
+ * Read all modified memos in from Pilot.
+ */
+void MemofileConduit::getModifiedFromPilot()
+{
+ FUNCTIONSETUP;
+
+ fMemoList.clear();
+
+ int currentRecord = 0;
+ PilotRecord *pilotRec;
+ PilotMemo *memo = 0;
+
+ while ((pilotRec = fDatabase->readNextModifiedRec()) != NULL) {
+ memo = new PilotMemo(pilotRec);
+ // we are syncing to both our filesystem and to the local
+ // database, so take care of the local database here
+ if (memo->isDeleted()) {
+ fLocalDatabase->deleteRecord(memo->id());
+ } else {
+ fLocalDatabase->writeRecord(pilotRec);
+ }
+
+ if ((!pilotRec->isSecret()) || _sync_private) {
+ fMemoList.append(memo);
+
+ DEBUGKPILOT << fname
+ << ": modified memo id: ["
+ << memo->id()
+ << "], title: ["
+ << memo->getTitle()
+ << "]" << endl;
+ } else {
+ DEBUGKPILOT << fname
+ << ": skipped secret modified record id: ["
+ << memo->id()
+ << "], title: ["
+ << memo->getTitle()
+ << "]" << endl;
+ }
+
+ KPILOT_DELETE(pilotRec);
+
+ currentRecord++;
+ }
+
+ DEBUGKPILOT << fname
+ << ": read: [" << fMemoList.count()
+ << "] modified records from palm." << endl;
+}
+
+
+/* slot */ void MemofileConduit::process()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname << ": Now in state " << fActionStatus << endl;
+}
+
+
+void MemofileConduit::listPilotMemos()
+{
+ FUNCTIONSETUP;
+
+ PilotMemo *memo;
+ for ( memo = fMemoList.first(); memo; memo = fMemoList.next() ) {
+ QString _category_name = fCategories[memo->category()];
+
+ DEBUGKPILOT << fConduitName
+ << ": listing record id: [" << memo->id()
+ << "] category id: [" << memo->category()
+ << "] category name: [" << _category_name
+ << "] title: [" << memo->getTitle()
+ << "]" << endl;
+ }
+}
+
+bool MemofileConduit::copyHHToPC()
+{
+ FUNCTIONSETUP;
+
+ getAllFromPilot();
+
+ _memofiles->eraseLocalMemos();
+
+ _memofiles->setPilotMemos(fMemoList);
+
+ _memofiles->save();
+
+ return true;
+
+}
+
+bool MemofileConduit::copyPCToHH()
+{
+ FUNCTIONSETUP;
+
+ // set category info from the filesystem, if we can.
+ // Note: This will reset both fCategories and fMemoAppInfo, so
+ // after this, we need to reinitialize our memofiles object...
+ setAppInfo();
+
+ // re-create our memofiles helper...
+ KPILOT_DELETE(_memofiles);
+ _memofiles = new Memofiles(fCategories, *fMemoAppInfo,
+ _memo_directory, *fCtrHH);
+
+ _memofiles->load(true);
+
+ QPtrList<Memofile> memofiles = _memofiles->getAll();
+
+ Memofile * memofile;
+
+ for ( memofile = memofiles.first(); memofile; memofile = memofiles.next() ) {
+ writeToPilot(memofile);
+ }
+
+ _memofiles->save();
+
+ // now that we've copied from the PC to our handheld, remove anything extra from the
+ // handheld...
+ deleteUnsyncedHHRecords();
+
+ return true;
+
+}
+
+void MemofileConduit::deleteUnsyncedHHRecords()
+{
+ FUNCTIONSETUP;
+ if ( syncMode()==SyncMode::eCopyPCToHH )
+ {
+ Pilot::RecordIDList ids=fDatabase->idList();
+ Pilot::RecordIDList::iterator it;
+ for ( it = ids.begin(); it != ids.end(); ++it )
+ {
+ if (!_memofiles->find(*it))
+ {
+ DEBUGKPILOT << fname
+ << "Deleting record with ID "<< *it <<" from handheld "
+ << "(is not on PC, and syncing with PC->HH direction)"
+ << endl;
+ fDatabase->deleteRecord(*it);
+ fLocalDatabase->deleteRecord(*it);
+ }
+ }
+ }
+}
+
+int MemofileConduit::writeToPilot(Memofile * memofile)
+{
+ FUNCTIONSETUP;
+
+ int oldid = memofile->id();
+
+ PilotRecord *r = memofile->pack();
+
+ if (!r) {
+ DEBUGKPILOT << fname
+ << ": ERROR: [" << memofile->toString()
+ << "] could not be written to the pilot."
+ << endl;
+ return -1;
+ }
+
+ int newid = fDatabase->writeRecord(r);
+ fLocalDatabase->writeRecord(r);
+
+ KPILOT_DELETE(r);
+
+ memofile->setID(newid);
+
+ QString status;
+ if (oldid <=0) {
+ fCtrHH->created();
+ status = "new to pilot";
+ } else {
+ fCtrHH->updated();
+ status = "updated";
+ }
+
+ DEBUGKPILOT << fname
+ << ": memofile: [" << memofile->toString()
+ << "] written to the pilot, [" << status << "]."
+ << endl;
+
+ return newid;
+}
+
+void MemofileConduit::deleteFromPilot(PilotMemo * memo)
+{
+ FUNCTIONSETUP;
+
+ PilotRecord *r = memo->pack();
+ if (r) {
+ r->setDeleted(true);
+ fDatabase->writeRecord(r);
+ fLocalDatabase->writeRecord(r);
+ }
+ KPILOT_DELETE(r);
+
+ fCtrHH->deleted();
+
+ DEBUGKPILOT << fname
+ << ": memo: [" << memo->getTitle()
+ << "] deleted from the pilot."
+ << endl;
+}
+
+bool MemofileConduit::sync()
+{
+ FUNCTIONSETUP;
+
+ _memofiles->load(false);
+
+ getModifiedFromPilot();
+
+ PilotMemo *memo;
+ for ( memo = fMemoList.first(); memo; memo = fMemoList.next() ) {
+ _memofiles->addModifiedMemo(memo);
+ }
+
+ QPtrList<Memofile> memofiles = _memofiles->getModified();
+
+ Memofile *memofile;
+ for ( memofile = memofiles.first(); memofile; memofile = memofiles.next() ) {
+ if (memofile->isDeleted()) {
+ deleteFromPilot(memofile);
+ } else {
+ writeToPilot(memofile);
+ }
+ }
+
+ _memofiles->save();
+
+ return true;
+}
+
+void MemofileConduit::cleanup()
+{
+ FUNCTIONSETUP;
+
+ fDatabase->resetSyncFlags();
+ fDatabase->cleanup();
+ fLocalDatabase->resetSyncFlags();
+ fLocalDatabase->cleanup();
+
+ fCtrPC->setEndCount(_memofiles->count());
+}
+
+
+#include "memofile-conduit.moc"
+