summaryrefslogtreecommitdiffstats
path: root/kpilot/conduits/memofileconduit
diff options
context:
space:
mode:
Diffstat (limited to 'kpilot/conduits/memofileconduit')
-rw-r--r--kpilot/conduits/memofileconduit/CMakeLists.txt44
-rw-r--r--kpilot/conduits/memofileconduit/Makefile.am16
-rw-r--r--kpilot/conduits/memofileconduit/design/SQD - copyHHToPC.jpgbin0 -> 111060 bytes
-rw-r--r--kpilot/conduits/memofileconduit/design/SQD - copyPCToHH.jpgbin0 -> 69573 bytes
-rw-r--r--kpilot/conduits/memofileconduit/design/SQD - detailed load.jpgbin0 -> 119635 bytes
-rw-r--r--kpilot/conduits/memofileconduit/design/SQD - sync.jpgbin0 -> 112438 bytes
-rw-r--r--kpilot/conduits/memofileconduit/memofile-conduit.cc567
-rw-r--r--kpilot/conduits/memofileconduit/memofile-conduit.desktop93
-rw-r--r--kpilot/conduits/memofileconduit/memofile-conduit.h92
-rw-r--r--kpilot/conduits/memofileconduit/memofile-factory.cc128
-rw-r--r--kpilot/conduits/memofileconduit/memofile-factory.h40
-rw-r--r--kpilot/conduits/memofileconduit/memofile.cc239
-rw-r--r--kpilot/conduits/memofileconduit/memofile.h113
-rw-r--r--kpilot/conduits/memofileconduit/memofileSettings.kcfgc7
-rw-r--r--kpilot/conduits/memofileconduit/memofileconduit.kcfg16
-rw-r--r--kpilot/conduits/memofileconduit/memofileconduit.xmi241
-rw-r--r--kpilot/conduits/memofileconduit/memofiles.cc700
-rw-r--r--kpilot/conduits/memofileconduit/memofiles.h96
-rw-r--r--kpilot/conduits/memofileconduit/setup_base.ui143
19 files changed, 2535 insertions, 0 deletions
diff --git a/kpilot/conduits/memofileconduit/CMakeLists.txt b/kpilot/conduits/memofileconduit/CMakeLists.txt
new file mode 100644
index 000000000..56994570f
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/CMakeLists.txt
@@ -0,0 +1,44 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(conduit_memofile_SRCS
+ memofile-factory.cc
+ memofile.cc
+ memofiles.cc
+ memofile-conduit.cc
+)
+
+set(conduit_memofile_UIS
+ setup_base.ui
+)
+
+set(conduit_memofile_KCFGS
+ memofileSettings.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_memofile_SRCS ${conduit_memofile_KCFGS})
+kde3_add_ui_files(conduit_memofile_SRCS ${conduit_memofile_UIS})
+kde3_automoc(${conduit_memofile_SRCS})
+add_library(conduit_memofile SHARED ${conduit_memofile_SRCS})
+
+set_target_properties(
+ conduit_memofile PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_memofile)
+
+install(
+ TARGETS conduit_memofile
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+install(
+ FILES memofile-conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES memofileconduit.kcfg DESTINATION ${KDE3_KCFG_DIR}
+)
diff --git a/kpilot/conduits/memofileconduit/Makefile.am b/kpilot/conduits/memofileconduit/Makefile.am
new file mode 100644
index 000000000..e4a244b51
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/Makefile.am
@@ -0,0 +1,16 @@
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+
+METASOURCES = AUTO
+
+servicedir = $(kde_servicesdir)
+service_DATA = memofile-conduit.desktop
+
+kde_module_LTLIBRARIES = conduit_memofile.la
+
+
+conduit_memofile_la_SOURCES = memofileSettings.kcfgc setup_base.ui \
+ memofile-factory.cc memofile.cc memofiles.cc memofile-conduit.cc
+conduit_memofile_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_memofile_la_LIBADD = ../../lib/libkpilot.la $(LIB_KDEUI) $(LIB_KFILE)
+
+kde_kcfg_DATA = memofileconduit.kcfg
diff --git a/kpilot/conduits/memofileconduit/design/SQD - copyHHToPC.jpg b/kpilot/conduits/memofileconduit/design/SQD - copyHHToPC.jpg
new file mode 100644
index 000000000..82cc11880
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/design/SQD - copyHHToPC.jpg
Binary files differ
diff --git a/kpilot/conduits/memofileconduit/design/SQD - copyPCToHH.jpg b/kpilot/conduits/memofileconduit/design/SQD - copyPCToHH.jpg
new file mode 100644
index 000000000..ef4254d43
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/design/SQD - copyPCToHH.jpg
Binary files differ
diff --git a/kpilot/conduits/memofileconduit/design/SQD - detailed load.jpg b/kpilot/conduits/memofileconduit/design/SQD - detailed load.jpg
new file mode 100644
index 000000000..4e0601f6a
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/design/SQD - detailed load.jpg
Binary files differ
diff --git a/kpilot/conduits/memofileconduit/design/SQD - sync.jpg b/kpilot/conduits/memofileconduit/design/SQD - sync.jpg
new file mode 100644
index 000000000..91299ce07
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/design/SQD - sync.jpg
Binary files differ
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"
+
diff --git a/kpilot/conduits/memofileconduit/memofile-conduit.desktop b/kpilot/conduits/memofileconduit/memofile-conduit.desktop
new file mode 100644
index 000000000..c453821f5
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile-conduit.desktop
@@ -0,0 +1,93 @@
+[Desktop Entry]
+Type=Service
+Name=Memo File
+Name[af]=Memo Lêer
+Name[bg]=Бележка
+Name[ca]=Fitxer de notes
+Name[cs]=Soubor s poznámkou
+Name[da]=Memo-fil
+Name[de]=Memo Datei
+Name[el]=Αρχείο υπομνήματος
+Name[eo]=Memo-dosiero
+Name[es]=Archivo de nota
+Name[et]=Memofail
+Name[eu]=Ohar fitxategia
+Name[fa]=پروندۀ Memo
+Name[fi]=Muistiotiedosto
+Name[fr]=Fichier mémo
+Name[fy]=Memotriem
+Name[ga]=Comhad Meamraim
+Name[gl]=Ficheiro Memo
+Name[hu]=Memófájl
+Name[is]=Minnismiðaskrá
+Name[it]=File appunti
+Name[ja]=メモファイル
+Name[ka]=ჩანიშვნა
+Name[kk]=Жазба файлы
+Name[km]=ឯកសារ​អនុស្សរណៈ
+Name[lt]=Memo byla
+Name[ms]=Fail Memo
+Name[nb]=Notatfil
+Name[nds]=Notiz-Datei
+Name[ne]=स्मृति फाइल
+Name[nl]=Memobestand
+Name[nn]=Memofil
+Name[pl]=Plik notatki
+Name[pt]=Ficheiro Memorando
+Name[pt_BR]=Arquivo Memo
+Name[ru]=Заметка
+Name[sk]=Memo súbor
+Name[sl]=Datoteka z opombami
+Name[sv]=Anteckningsfil
+Name[ta]=மெமோ கோப்பு
+Name[tr]=Hatırlatma Dosyası
+Name[uk]=Файл примітки
+Name[zh_CN]=备忘文件
+Name[zh_TW]=Memo 檔
+Comment=This conduit syncs your handheld memos with a local directory.
+Comment[af]=Hierdie pad sinkroniseer jou draagbare toestel se memos met 'n plaaslike gids.
+Comment[bg]=Синхронизация на бележките на KDE с мобилни устройства.
+Comment[ca]=Aquest conducte sincronitza les notes de l'agenda electrònica amb un directori local.
+Comment[cs]=Toto propojení synchronizuje vaše poznámky v PDA s lokálním adresářem.
+Comment[da]=Denne kanal synkroniserer dine håndholdte memoer med en lokal mappe.
+Comment[de]=Abgleich der Memos von Taschencomputer und einem lokalen Ordner
+Comment[el]=Αυτός ο σύνδεσμος συγχρονίζει τα υπομνήματα του υπολογιστή παλάμης σας με έναν τοπικό κατάλογο.
+Comment[eo]=Tiu kanalo sinkronigas viajn poŝkomputil-memoojn kun loka dosierujo.
+Comment[es]=Este conducto sincroniza las notas de su agenda electrónica con el directorio local.
+Comment[et]=See kanal sünkroniseerib pihuarvutis ja arvutis olevad memod.
+Comment[eu]=Kanal honek zure agendako oharrak direktorio lokal batekin sinkronizatzen ditu.
+Comment[fa]=این لوله، memo‌های دستی خود را با فهرست راهنمای محلی همگام‌سازی می‌کند.
+Comment[fi]=Tämä yhdyskäytävä synkronoi taskutietokoneen muistiot paikalliseen kansioon.
+Comment[fr]=Ce canal synchronise les mémos du Palm avec ceux de KDE.
+Comment[fy]=Dit conduit syngronisearret de memo's fan jo handheld mei in lokale triemtafel.
+Comment[gl]=Este conducto sincroniza os memos do seu aparello portátil cun cartafol local.
+Comment[hu]=Ezzel a csatolóval egy kézi számítógép memóit lehet szinkronizálni a helyi címjegyzékkel.
+Comment[is]=Þessi rás samstillir minnismiða lófatölvunnar þinnar við staðbundna möppu.
+Comment[it]=Questo condotto sincronizza gli appunti del tuo palmare con una cartella locale.
+Comment[ja]=このコンジットはハンドヘルドのメモをローカルのディレクトリと同期させます。
+Comment[ka]=ეს არხი თქვენი პორტატიული მოწყობილობის ლოკალურ დირექტორიასთან სინქრონიზაციას ახდენს .
+Comment[kk]=Қалта құрылғыдағы жазбаларды қапшықтағы файлымен қадамдастыру арнасы.
+Comment[km]=បំពង់​នេះ​អាច​ឲ្យ​អនុស្សរណៈ​ឧបករណ៍​យួរ​ដៃ​របស់​អ្នក ធ្វើ​សមកាលកម្ម​ជាមួយ​នឹង​ថត​មូលដ្ឋាន ។​
+Comment[lt]=Šis kanalas sinchronizuoja Jūsų užrašus su vietiniu aplanku.
+Comment[ms]=Saluran ini mensegerakkan memo komputer telapak anda dengan direktori setempat.
+Comment[nb]=Denne kanalen synkroniserer PDA-ens notater med en lokal mappe.
+Comment[nds]=Synkroniseert de Notizen op den Handreekner mit en lokaal Orner.
+Comment[ne]=यो कन्ड्युटले स्थानीय डाइरेक्टरीमा तपाईँका ह्यान्डहेल्ड मेमो सिन्क गर्दछ ।
+Comment[nl]=Dit conduit synchroniseert de memo's van uw handheld met een lokale map.
+Comment[pl]=Ten łącznik synchronizuje notatki z palmtopa z lokalnym katalogiem.
+Comment[pt]=Esta conduta sincroniza os memorandos do seu PDA com uma pasta local.
+Comment[pt_BR]=Este conduíte sincroniza as anotações no seu handheld com um diretório local.
+Comment[ru]=Канал синхронизации заметок КПК и KDE.
+Comment[sk]=Táto spojka synchronizuje adresár vášho prenosného zariadenia s lokálnym priečinkom.
+Comment[sl]=Ta veznik usklajuje opombe v ročnem računalniku s krajevnim imenikom.
+Comment[sr]=Овај провод синхронизује белешке на вашем ручном рачунару са локалним директоријумом.
+Comment[sr@Latn]=Ovaj provod sinhronizuje beleške na vašem ručnom računaru sa lokalnim direktorijumom.
+Comment[sv]=Den här kanalen synkroniserar handdatorns anteckningar med en lokal katalog.
+Comment[ta]=இந்த குழாய் கையில் உள்ள முகவரிப்புத்தகத்தை கேடிஇயின் முகவரிப்புத்தகத்தோடு ஒத்திசைக்கிறது
+Comment[tr]=Bu bileşen el bilgisayarı hatırlatmalarını yerel bir dosyaya aktarır veya alır.
+Comment[uk]=Цей акведук синхронізує примітки кишенькового пристрою з локальним каталогом.
+Comment[zh_CN]=此管道会将您手持设备中的备忘与本地目录同步。
+Comment[zh_TW]=此軟體同步您的 handheld memo 及本地端目錄。
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_memofile
diff --git a/kpilot/conduits/memofileconduit/memofile-conduit.h b/kpilot/conduits/memofileconduit/memofile-conduit.h
new file mode 100644
index 000000000..08fdbd0f7
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile-conduit.h
@@ -0,0 +1,92 @@
+#ifndef _MEMOFILE_MEMOFILE_CONDUIT_H
+#define _MEMOFILE_MEMOFILE_CONDUIT_H
+/* memofile-conduit.h KPilot
+**
+** Copyright (C) 2004-2007 by 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 <pi-memo.h>
+
+#include "plugin.h"
+
+#include "memofiles.h"
+
+class PilotMemo;
+
+class MemofileConduit : public ConduitAction
+{
+Q_OBJECT
+public:
+ MemofileConduit(KPilotLink *,
+ const char *name=0L,
+ const QStringList &args = QStringList());
+ virtual ~MemofileConduit();
+
+protected:
+ virtual bool exec();
+
+
+protected slots:
+ void process();
+
+private:
+ // configuration settings...
+ QString _DEFAULT_MEMODIR;
+ QString _memo_directory;
+ bool _sync_private;
+
+ PilotMemoInfo *fMemoAppInfo;
+ QPtrList<PilotMemo> fMemoList;
+
+ // our categories
+ MemoCategoryMap fCategories;
+
+ Memofiles * _memofiles;
+
+
+ bool readConfig();
+ bool getAppInfo();
+ bool setAppInfo();
+
+ bool initializeFromPilot();
+ bool loadPilotCategories();
+
+ void listPilotMemos();
+
+ void getAllFromPilot();
+ void getModifiedFromPilot();
+
+ bool copyHHToPC();
+ bool copyPCToHH();
+ void deleteUnsyncedHHRecords();
+ bool sync();
+
+ int writeToPilot(Memofile * memofile);
+ void deleteFromPilot(PilotMemo* memo);
+
+ void cleanup();
+
+};
+
+#endif
diff --git a/kpilot/conduits/memofileconduit/memofile-factory.cc b/kpilot/conduits/memofileconduit/memofile-factory.cc
new file mode 100644
index 000000000..e373a0185
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile-factory.cc
@@ -0,0 +1,128 @@
+/* memofile-factory.cc KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+**
+** This file defines the factory for the memofile-conduit plugin.
+*/
+
+/*
+** 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 <qtabwidget.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+
+#include <kconfig.h>
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <kurlrequester.h>
+
+#include "setup_base.h"
+#include "memofile-conduit.h"
+#include "memofileSettings.h"
+
+#include "pluginfactory.h"
+
+class MemofileConduitConfig : public ConduitConfigBase
+{
+public:
+ MemofileConduitConfig(QWidget *parent=0L, const char *n=0L);
+ virtual void commit();
+ virtual void load();
+protected:
+ MemofileWidget *fConfigWidget;
+} ;
+
+MemofileConduitConfig::MemofileConduitConfig(QWidget *p, const char *n) :
+ ConduitConfigBase(p,n),
+ fConfigWidget(new MemofileWidget(p))
+{
+ FUNCTIONSETUP;
+ fConduitName = i18n("Memofile");
+ KAboutData *about = new KAboutData("MemofileConduit",
+ I18N_NOOP("Memofile Conduit for KPilot"),
+ KPILOT_VERSION,
+ I18N_NOOP("Configures the Memofile Conduit for KPilot"),
+ KAboutData::License_GPL,
+ "(C) 2004, Jason 'vanRijn' Kasper");
+ about->addAuthor("Jason 'vanRijn' Kasper",
+ I18N_NOOP("Primary Author"),
+ "vR@movingparts.net",
+ "http://www.cs.kun.nl/~adridg/kpilot");
+
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,about);
+ fWidget=fConfigWidget;
+ QObject::connect(fConfigWidget->fDirectory,SIGNAL(textChanged(const QString&)),
+ this,SLOT(modified()));
+ QObject::connect(fConfigWidget->fSyncPrivate,SIGNAL(toggled(bool)),
+ this,SLOT(modified()));
+
+}
+
+/* virtual */ void MemofileConduitConfig::commit()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname
+ << ": Directory="
+ << fConfigWidget->fDirectory->url()
+ << endl;
+
+ MemofileConduitSettings::setDirectory( fConfigWidget->fDirectory->url() );
+ MemofileConduitSettings::setSyncPrivate( fConfigWidget->fSyncPrivate->isChecked() );
+ MemofileConduitSettings::self()->writeConfig();
+ unmodified();
+}
+
+/* virtual */ void MemofileConduitConfig::load()
+{
+ FUNCTIONSETUP;
+ MemofileConduitSettings::self()->readConfig();
+
+ fConfigWidget->fDirectory->setURL( MemofileConduitSettings::directory() );
+ fConfigWidget->fSyncPrivate->setChecked( MemofileConduitSettings::syncPrivate() );
+
+ DEBUGKPILOT << fname
+ << ": Read Directory: ["
+ << fConfigWidget->fDirectory->url()
+ << "], sync private records: ["
+ << fConfigWidget->fSyncPrivate
+ << "]" << endl;
+
+ unmodified();
+}
+
+
+
+extern "C"
+{
+
+void *init_conduit_memofile()
+{
+ return new ConduitFactory<MemofileConduitConfig,MemofileConduit>(0,"memofileconduit");
+}
+
+unsigned long version_conduit_memofile = Pilot::PLUGIN_API;
+
+}
+
diff --git a/kpilot/conduits/memofileconduit/memofile-factory.h b/kpilot/conduits/memofileconduit/memofile-factory.h
new file mode 100644
index 000000000..b42fb6577
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile-factory.h
@@ -0,0 +1,40 @@
+#ifndef _KPILOT_MEMOFILE_FACTORY_H
+#define _KPILOT_MEMOFILE_FACTORY_H
+/* memofile-factory.h KPilot
+**
+** Copyright (C) 2004-2007 by Jason 'vanRijn' Kasper
+**
+** This file defines the factory for the Memofile-conduit plugin.
+** It also defines the class for the behavior of the setup dialog.
+*/
+
+/*
+** 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
+*/
+
+
+extern "C"
+{
+
+void *init_libmemofileconduit();
+
+}
+
+#endif
diff --git a/kpilot/conduits/memofileconduit/memofile.cc b/kpilot/conduits/memofileconduit/memofile.cc
new file mode 100644
index 000000000..1428c487d
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile.cc
@@ -0,0 +1,239 @@
+/* memofile.cc KPilot
+**
+** Copyright (C) 2004-2007 by 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 "memofile.h"
+
+Memofile::Memofile(PilotMemo * memo, QString categoryName, QString fileName, QString baseDirectory) :
+ PilotMemo(memo,memo->text()), _categoryName(categoryName), _filename(fileName), _baseDirectory(baseDirectory)
+{
+ _lastModified = 0;
+ _size = 0;
+ _modified = _modifiedByPalm = false;
+}
+
+Memofile::Memofile(recordid_t id, int category, uint lastModifiedTime, uint size,
+ QString categoryName, QString fileName, QString baseDirectory) :
+ PilotMemo(), _categoryName(categoryName),
+ _filename(fileName),_baseDirectory(baseDirectory)
+{
+ setID(id);
+ PilotRecordBase::setCategory(category);
+ _lastModified = lastModifiedTime;
+ _size = size;
+ _modified = _modifiedByPalm = false;
+}
+
+Memofile::Memofile(int category, QString categoryName, QString fileName, QString baseDirectory) :
+ PilotMemo(),
+ _categoryName(categoryName), _filename(fileName), _baseDirectory(baseDirectory)
+{
+ setID(0);
+ _new = true;
+ PilotRecordBase::setCategory(category);
+ _modified = true;
+ _modifiedByPalm = false;
+ _lastModified = 0;
+ _size = 0;
+}
+
+bool Memofile::load()
+{
+ FUNCTIONSETUP;
+ if (filename().isEmpty()) {
+ DEBUGKPILOT << fname
+ << ": I was asked to load, but have no filename to load. "
+ << endl;
+ return false;
+ }
+
+ QFile f( filenameAbs() );
+ if ( !f.open( IO_ReadOnly ) ) {
+ DEBUGKPILOT << fname
+ << ": Couldn't open file: [" << filenameAbs() << "] to read. "
+ << endl;
+ return false;
+ }
+
+ QTextStream ts( &f );
+
+ QString text,title,body;
+ title = filename();
+ body = ts.read();
+
+ // funky magic. we want the text of the memofile to have the filename
+ // as the first line....
+ if (body.startsWith(title)) {
+ text = body;
+ } else {
+ DEBUGKPILOT << fname
+ << ": text of your memofile: [" << filename()
+ << "] didn't include the filename as the first line. fixing it..." << endl;
+ text = title + CSL1("\n") + body;
+ }
+
+ // check length of text. if it's over the allowable length, warn user.
+ // NOTE: We don't need to truncate this here, since PilotMemo::setText()
+ // does it for us.
+ int _len = text.length();
+ int _maxlen = PilotMemo::MAX_MEMO_LEN;
+ if (_len > _maxlen) {
+ DEBUGKPILOT << fname << ": memofile: [" << filename()
+ << "] length: [" << _len << "] is over maximum: ["
+ << _maxlen << "] and will be truncated to fit." << endl;
+ }
+
+ setText(text);
+ f.close();
+
+ return true;
+}
+
+void Memofile::setID(recordid_t i)
+{
+ if (i != id())
+ _modifiedByPalm = true;
+
+ PilotMemo::setID(i);
+}
+
+bool Memofile::save()
+{
+ bool result = true;
+
+ if ((isModified() && isLoaded()) || _modifiedByPalm) {
+ result = saveFile();
+ }
+
+ return result;
+}
+
+bool Memofile::deleteFile()
+{
+ FUNCTIONSETUP;
+ DEBUGKPILOT << fname
+ << ": deleting file: [" << filenameAbs() << "]." << endl;
+ return QFile::remove(filenameAbs());
+
+}
+
+bool Memofile::saveFile()
+{
+ FUNCTIONSETUP;
+
+ if (filename().isEmpty()) {
+ DEBUGKPILOT << fname
+ << ": I was asked to save, but have no filename to save to. "
+ << endl;
+ return false;
+ }
+
+ DEBUGKPILOT << fname
+ << ": saving memo to file: ["
+ << filenameAbs() << "]" << endl;
+
+
+ QFile f( filenameAbs() );
+ if ( !f.open( IO_WriteOnly ) ) {
+ DEBUGKPILOT << fname
+ << ": Couldn't open file: [" << filenameAbs() << "] to write your memo to. "
+ << "This won't end well." << endl;
+ return false;
+ }
+
+ QTextStream stream(&f);
+ stream << text() << endl;
+ f.close();
+
+ _lastModified = getFileLastModified();
+ _size = getFileSize();
+
+ return true;
+
+}
+
+bool Memofile::isModified(void)
+{
+ // first, check to see if this file is deleted....
+ if (!fileExists()) {
+ return true;
+ }
+
+ bool modByTimestamp = false;
+ bool modBySize = false;
+
+ if (_lastModified > 0)
+ modByTimestamp = isModifiedByTimestamp();
+
+ if (_size > 0)
+ modBySize = isModifiedBySize();
+
+ bool ret = _modified || modByTimestamp || modBySize;
+
+ return ret;
+}
+
+bool Memofile::isModifiedByTimestamp()
+{
+ if (_lastModified <=0) {
+ return true;
+ }
+
+ uint lastModifiedTime = getFileLastModified();
+ if ( lastModifiedTime != _lastModified) {
+ return true;
+ }
+
+ return false;
+}
+
+bool Memofile::isModifiedBySize()
+{
+ if (_size <=0) {
+ return true;
+ }
+
+ uint size = getFileSize();
+ if ( size != _size) {
+ return true;
+ }
+
+ return false;
+}
+
+uint Memofile::getFileLastModified()
+{
+ QFileInfo f = QFileInfo(filenameAbs());
+ uint lastModifiedTime = f.lastModified().toTime_t();
+ return lastModifiedTime;
+}
+
+uint Memofile::getFileSize()
+{
+ QFileInfo f = QFileInfo(filenameAbs());
+ uint size = f.size();
+ return size;
+}
diff --git a/kpilot/conduits/memofileconduit/memofile.h b/kpilot/conduits/memofileconduit/memofile.h
new file mode 100644
index 000000000..27931cdfe
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofile.h
@@ -0,0 +1,113 @@
+#ifndef _MEMOFILE_MEMOFILE_H
+#define _MEMOFILE_MEMOFILE_H
+/* memofile.h KPilot
+**
+** Copyright (C) 2004-2007 by 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"
+
+// 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 <qfile.h>
+#include <qdir.h>
+#include <qtextstream.h>
+#include <qtextcodec.h>
+
+#include "pilotMemo.h"
+
+#include "memofiles.h"
+
+/**
+ * Class that represents our filesystem memo.
+ */
+class Memofile : public PilotMemo
+{
+ public:
+ Memofile(PilotMemo * memo, QString categoryName, QString fileName, QString baseDirectory);
+ Memofile(recordid_t id, int category, uint lastModifiedTime, uint size, QString categoryName, QString filename, QString baseDirectory);
+ Memofile(int category, QString categoryName, QString fileName, QString baseDirectory);
+
+ uint lastModified() const { return _lastModified; } ;
+ uint size() const { return _size; } ;
+
+ void setModifiedByPalm(bool mod) { _modifiedByPalm = mod; } ;
+ void setModified(bool modified) { _modified = modified; } ;
+
+ bool isModified(void);
+ bool isModifiedByPalm() { return _modifiedByPalm; } ;
+ bool isLoaded(void) { return (! text().isEmpty()); } ;
+ bool isNew(void) { return _new; } ;
+
+ bool load();
+
+ bool fileExists() { return QFile::exists(filenameAbs()); } ;
+
+ void setID(recordid_t id);
+
+ bool save();
+ bool deleteFile();
+
+ QString toString() {
+ return CSL1("id: [") + QString::number(id())
+ + CSL1("], category:[") + _categoryName
+ + CSL1("], filename: [") + _filename + CSL1("]");
+ } ;
+ const QString & getCategoryName() { return _categoryName; } ;
+ const QString & getFilename() { return _filename; } ;
+ const QString & filename() { return _filename; } ;
+
+ private:
+ bool saveFile();
+ bool isModifiedByTimestamp();
+ bool isModifiedBySize();
+
+ QString filenameAbs() { return dirName() + filename(); } ;
+ QString dirName() { return _baseDirectory + QDir::separator() + _categoryName + QDir::separator(); } ;
+ bool setCategory(const QString &label);
+ uint getFileLastModified();
+ uint getFileSize();
+
+ bool _modifiedByPalm;
+ bool _modified;
+ bool _new;
+ uint _lastModified;
+ uint _size;
+
+ QString _categoryName;
+ QString _filename;
+ QString _baseDirectory;
+} ;
+
+#endif
diff --git a/kpilot/conduits/memofileconduit/memofileSettings.kcfgc b/kpilot/conduits/memofileconduit/memofileSettings.kcfgc
new file mode 100644
index 000000000..3d1373b88
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofileSettings.kcfgc
@@ -0,0 +1,7 @@
+File=memofileconduit.kcfg
+ClassName= MemofileConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/memofileconduit/memofileconduit.kcfg b/kpilot/conduits/memofileconduit/memofileconduit.kcfg
new file mode 100644
index 000000000..506e040ed
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofileconduit.kcfg
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE kcfg SYSTEM "http://www.kde.org/standards/kcfg/1.0/kcfg.dtd">
+<kcfg><kcfgfile name="kpilotrc"/>
+ <group name="memofile-conduit">
+ <entry name="Directory" type="Path">
+ <label>What directory do you want to sync your PDA's memos with?</label>
+ <default>$HOME/MyMemos</default>
+ </entry>
+ <entry name="SyncPrivate" type="Bool">
+ <label>Do you want to sync your private records to the filesystem?</label>
+ <default>true</default>
+ </entry>
+
+ </group>
+
+</kcfg>
diff --git a/kpilot/conduits/memofileconduit/memofileconduit.xmi b/kpilot/conduits/memofileconduit/memofileconduit.xmi
new file mode 100644
index 000000000..33ff89f85
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofileconduit.xmi
@@ -0,0 +1,241 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XMI xmlns:UML="org.omg/standards/UML" verified="false" timestamp="" xmi.version="1.2" >
+ <XMI.header>
+ <XMI.documentation>
+ <XMI.exporter>umbrello uml modeller http://uml.sf.net</XMI.exporter>
+ <XMI.exporterVersion>1.2.90</XMI.exporterVersion>
+ <XMI.exporterEncoding>UnicodeUTF8</XMI.exporterEncoding>
+ </XMI.documentation>
+ <XMI.model xmi.name="umbrelloJSFhpc" href="/tmp/kde-gideon/umbrelloJSFhpc.tmp" />
+ <XMI.metamodel xmi.name="UML" href="UML.xml" xmi.version="1.3" />
+ </XMI.header>
+ <XMI.content>
+ <UML:Model>
+ <UML:Stereotype visibility="public" xmi.id="3" name="datatype" />
+ <UML:Stereotype visibility="public" xmi.id="18" name="enum" />
+ <UML:Stereotype visibility="public" xmi.id="35" name="typedef" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="2" name="int" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="4" name="char" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="5" name="bool" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="6" name="float" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="7" name="double" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="8" name="long" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="9" name="short" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="10" name="string" />
+ <UML:Class visibility="public" xmi.id="11" name="MemofileConduit" >
+ <UML:Operation visibility="public" xmi.id="12" type="" name="MemofileConduit" >
+ <UML:Parameter visibility="public" xmi.id="13" value="" type="KPilotDeviceLink*" />
+ <UML:Parameter visibility="public" xmi.id="14" value="" type="const char*" name="name" />
+ <UML:Parameter visibility="public" xmi.id="15" value="" type="const QStringList&amp;" name="args" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="16" type="" name="~ MemofileConduit" />
+ <UML:Operation visibility="protected" xmi.id="26" type="bool" name="exec" />
+ <UML:Operation visibility="protected" xmi.id="27" type="void" name="listPilotMemos" />
+ <UML:Operation visibility="protected" xmi.id="28" type="void" name="process" />
+ <UML:Operation visibility="private" xmi.id="43" type="bool" name="readConfig" />
+ <UML:Operation visibility="private" xmi.id="44" type="void" name="getAppInfo" />
+ <UML:Operation visibility="private" xmi.id="45" type="QString" name="getCategoryName" >
+ <UML:Parameter visibility="public" xmi.id="46" value="" type="int" name="category" />
+ </UML:Operation>
+ <UML:Operation visibility="private" xmi.id="47" type="bool" name="initializeFromPilot" />
+ <UML:Operation visibility="private" xmi.id="48" type="bool" name="loadPilotMemos" />
+ <UML:Operation visibility="private" xmi.id="49" type="bool" name="loadPilotCategories" />
+ <UML:Operation visibility="private" xmi.id="50" type="bool" name="initializeFromFilesystem" />
+ <UML:Operation visibility="private" xmi.id="51" type="bool" name="initializeMemofileList" />
+ <UML:Operation visibility="private" xmi.id="52" type="bool" name="checkDirectory" >
+ <UML:Parameter visibility="public" xmi.id="53" value="" type="QString" name="dir" />
+ </UML:Operation>
+ <UML:Operation visibility="private" xmi.id="54" type="bool" name="ensureFilesystemReady" />
+ <UML:Operation visibility="private" xmi.id="55" type="bool" name="copyHHToPC" />
+ <UML:Operation visibility="private" xmi.id="56" type="bool" name="saveCategoriesToFilesystem" />
+ <UML:Operation visibility="private" xmi.id="57" type="bool" name="saveMemoInfoToFilesystem" />
+ <UML:Operation visibility="private" xmi.id="58" type="bool" name="saveMemosToFilesystem" />
+ <UML:Operation visibility="private" xmi.id="59" type="bool" name="saveAsText" >
+ <UML:Parameter visibility="public" xmi.id="60" value="" type="const QString&amp;" name="fileName" />
+ <UML:Parameter visibility="public" xmi.id="61" value="" type="Memofile*" name="theMemo" />
+ </UML:Operation>
+ <UML:Attribute visibility="private" xmi.id="29" value="" type="QString" name="_DEFAULT_MEMODIR" />
+ <UML:Attribute visibility="private" xmi.id="30" value="" type="QString" name="_memo_directory" />
+ <UML:Attribute visibility="private" xmi.id="31" value="" type="bool" name="_sync_private" />
+ <UML:Attribute visibility="private" xmi.id="32" value="" type="QPtrList&lt; PilotMemo >" name="fMemoList" />
+ <UML:Attribute visibility="private" xmi.id="33" value="" type="struct MemoAppInfo" name="fMemoAppInfo" />
+ <UML:Attribute visibility="private" xmi.id="37" value="" type="QPtrList&lt; Memofile >" name="fMemofileList" />
+ <UML:Attribute visibility="private" xmi.id="38" value="" type="int" name="fRecordIndex" />
+ <UML:Attribute visibility="private" xmi.id="39" value="" type="QTimer*" name="fTimer" />
+ <UML:Attribute visibility="private" xmi.id="40" value="" type="int" name="fCounter" />
+ <UML:Attribute visibility="private" xmi.id="41" value="" type="int" name="fDeleteCounter" />
+ <UML:Attribute visibility="private" xmi.id="42" value="" type="int" name="fModifyCounter" />
+ <UML:Enumeration stereotype="18" visibility="public" xmi.id="17" name="Status" >
+ <UML:EnumerationLiteral visibility="public" xmi.id="19" name="Init" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="20" name="ModifiedFilesToPilot" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="21" name="DeleteFilesOnPilot" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="22" name="NewFilesToPilot" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="23" name="MemosToFiles" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="24" name="Cleanup" />
+ <UML:EnumerationLiteral visibility="public" xmi.id="25" name="Done" />
+ </UML:Enumeration>
+ <UML:Class stereotype="35" visibility="public" xmi.id="34" name="MemoCategoryMap" />
+ </UML:Class>
+ <UML:Class visibility="public" xmi.id="63" name="Memofiles" >
+ <UML:Operation visibility="public" xmi.id="80" type="Memofiles" name="Memofiles" >
+ <UML:Parameter visibility="public" xmi.id="81" value="" type="QMap" name="categories" />
+ <UML:Parameter visibility="public" xmi.id="82" value="" type="QString" name="baseDirectory" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="87" type="void" name="load" >
+ <UML:Parameter visibility="public" xmi.id="88" value="" type="bool" name="loadAll" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="89" type="QPtrList&lt;Memofile>" name="getAll" />
+ <UML:Operation visibility="public" xmi.id="90" type="void" name="save" />
+ <UML:Operation visibility="public" xmi.id="91" type="void" name="eraseLocalMemos" />
+ <UML:Operation visibility="public" xmi.id="95" type="void" name="setModified" >
+ <UML:Parameter visibility="public" xmi.id="96" value="" type="QPtrList&lt;PilotMemo>" name="memos" />
+ </UML:Operation>
+ <UML:Operation visibility="private" xmi.id="97" type="void" name="ensureDirectoryReady" />
+ <UML:Operation visibility="public" xmi.id="98" type="void" name="loadIds" />
+ <UML:Operation visibility="public" xmi.id="99" type="Memofile" name="find" >
+ <UML:Parameter visibility="public" xmi.id="100" value="" type="QString" name="category" />
+ <UML:Parameter visibility="public" xmi.id="101" value="" type="QString" name="filename" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="102" type="void" name="addModified" >
+ <UML:Parameter visibility="public" xmi.id="103" value="" type="PilotMemo *" name="memo" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="104" type="QPtrList&lt;Memofile>" name="getModified" />
+ <UML:Attribute visibility="private" xmi.id="83" value="" type="QMap" name="_categories" />
+ <UML:Attribute visibility="private" xmi.id="85" value="" type="QString" name="_baseDirectory" />
+ <UML:Attribute visibility="private" xmi.id="93" value="" type="QPtrList&lt;Memofile>" name="_memofiles" />
+ </UML:Class>
+ <UML:Class visibility="public" xmi.id="64" name="Memofile" >
+ <UML:Operation visibility="public" xmi.id="65" type="" name="Memofile" >
+ <UML:Parameter visibility="public" xmi.id="66" value="" type="PilotMemo*" name="memo" />
+ <UML:Parameter visibility="public" xmi.id="67" value="" type="QString" name="categoryName" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="68" type="" name="Memofile" >
+ <UML:Parameter visibility="public" xmi.id="69" value="" type="recordid_t" name="id" />
+ <UML:Parameter visibility="public" xmi.id="70" value="" type="int" name="category" />
+ <UML:Parameter visibility="public" xmi.id="71" value="" type="QString" name="categoryName" />
+ <UML:Parameter visibility="public" xmi.id="72" value="" type="uint" name="lastModifiedTime" />
+ <UML:Parameter visibility="public" xmi.id="73" value="" type="QString" name="filename" />
+ <UML:Parameter visibility="public" xmi.id="74" value="" type="QString" name="text" />
+ </UML:Operation>
+ <UML:Operation visibility="public" xmi.id="75" type="uint" name="lastModified" />
+ <UML:Operation visibility="public" xmi.id="76" type="QString" name="filename" />
+ <UML:Attribute visibility="private" xmi.id="77" value="" type="uint" name="_lastModified" />
+ <UML:Attribute visibility="private" xmi.id="78" value="" type="QString" name="_categoryName" />
+ <UML:Attribute visibility="private" xmi.id="79" value="" type="QString" name="_filename" />
+ </UML:Class>
+ <UML:DataType stereotype="3" visibility="public" xmi.id="84" name="QMap" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="86" name="QString" />
+ <UML:DataType stereotype="3" visibility="public" xmi.id="94" name="QPtrList&lt;Memofile>" />
+ <UML:Association visibility="public" xmi.id="36" >
+ <UML:Association.connection>
+ <UML:AssociationEndRole visibility="public" aggregation="composite" type="11" />
+ <UML:AssociationEndRole visibility="private" type="34" />
+ </UML:Association.connection>
+ </UML:Association>
+ </UML:Model>
+ </XMI.content>
+ <XMI.extensions xmi.extender="umbrello" >
+ <docsettings viewid="62" documentation="" uniqueid="107" />
+ <diagrams>
+ <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="807" snapy="10" showatts="1" xmi.id="1" documentation="" type="402" showops="1" showpackage="0" name="class diagram" localid="30000" showstereotype="0" showscope="1" snapcsgrid="0" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="591" >
+ <widgets/>
+ <messages/>
+ <associations/>
+ </diagram>
+ <diagram snapgrid="0" showattsig="1" fillcolor="#ffffc0" linewidth="0" zoom="100" showgrid="0" showopsig="1" usefillcolor="1" snapx="10" canvaswidth="999" snapy="10" showatts="1" xmi.id="62" documentation="" type="402" showops="1" showpackage="0" name="memofile classes" localid="30000" showstereotype="0" showscope="1" snapcsgrid="0" font="Sans,10,-1,5,50,0,0,0,0,0" linecolor="#ff0000" canvasheight="630" >
+ <widgets>
+ <classwidget usesdiagramfillcolour="1" width="543" showattsigs="601" usesdiagramusefillcolour="1" x="428" linecolour="none" y="62" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="1" fillcolour="none" height="544" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="11" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Sans,10,-1,5,75,0,0,0,0,0" />
+ <classwidget usesdiagramfillcolour="1" width="432" showattsigs="601" usesdiagramusefillcolour="1" x="17" linecolour="none" y="33" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="1" fillcolour="none" height="255" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="63" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Sans,10,-1,5,75,0,0,0,0,0" />
+ <classwidget usesdiagramfillcolour="1" width="767" showattsigs="601" usesdiagramusefillcolour="1" x="3" linecolour="none" y="467" showopsigs="601" linewidth="none" usesdiagramlinewidth="1" usesdiagramlinecolour="1" fillcolour="none" height="136" usefillcolor="1" showpubliconly="0" showattributes="1" isinstance="0" xmi.id="64" showoperations="1" showpackage="0" showscope="1" showstereotype="0" font="Sans,10,-1,5,75,0,0,0,0,0" />
+ </widgets>
+ <messages/>
+ <associations/>
+ </diagram>
+ </diagrams>
+ <listview>
+ <listitem open="1" type="800" id="-1" label="Views" >
+ <listitem open="1" type="801" id="-1" label="Logical View" >
+ <listitem open="0" type="807" id="1" label="class diagram" />
+ <listitem open="0" type="807" id="62" label="memofile classes" />
+ <listitem open="0" type="813" id="64" >
+ <listitem open="0" type="814" id="78" />
+ <listitem open="0" type="814" id="79" />
+ <listitem open="0" type="814" id="77" />
+ <listitem open="0" type="815" id="65" />
+ <listitem open="0" type="815" id="68" />
+ <listitem open="0" type="815" id="76" />
+ <listitem open="0" type="815" id="75" />
+ </listitem>
+ <listitem open="0" type="813" id="11" >
+ <listitem open="1" type="813" id="34" />
+ <listitem open="0" type="814" id="29" />
+ <listitem open="0" type="814" id="30" />
+ <listitem open="0" type="814" id="31" />
+ <listitem open="0" type="814" id="40" />
+ <listitem open="0" type="814" id="41" />
+ <listitem open="0" type="814" id="33" />
+ <listitem open="0" type="814" id="32" />
+ <listitem open="0" type="814" id="37" />
+ <listitem open="0" type="814" id="42" />
+ <listitem open="0" type="814" id="38" />
+ <listitem open="0" type="814" id="39" />
+ <listitem open="0" type="815" id="12" />
+ <listitem open="0" type="815" id="52" />
+ <listitem open="0" type="815" id="55" />
+ <listitem open="0" type="815" id="54" />
+ <listitem open="0" type="815" id="26" />
+ <listitem open="0" type="815" id="44" />
+ <listitem open="0" type="815" id="45" />
+ <listitem open="0" type="815" id="50" />
+ <listitem open="0" type="815" id="47" />
+ <listitem open="0" type="815" id="51" />
+ <listitem open="0" type="815" id="27" />
+ <listitem open="0" type="815" id="49" />
+ <listitem open="0" type="815" id="48" />
+ <listitem open="0" type="815" id="28" />
+ <listitem open="0" type="815" id="43" />
+ <listitem open="0" type="815" id="59" />
+ <listitem open="0" type="815" id="56" />
+ <listitem open="0" type="815" id="57" />
+ <listitem open="0" type="815" id="58" />
+ <listitem open="0" type="815" id="16" />
+ <listitem open="1" type="831" id="17" />
+ </listitem>
+ <listitem open="1" type="813" id="63" >
+ <listitem open="0" type="814" id="85" />
+ <listitem open="0" type="814" id="83" />
+ <listitem open="0" type="814" id="93" />
+ <listitem open="0" type="815" id="80" />
+ <listitem open="0" type="815" id="102" />
+ <listitem open="0" type="815" id="97" />
+ <listitem open="0" type="815" id="91" />
+ <listitem open="0" type="815" id="99" />
+ <listitem open="0" type="815" id="89" />
+ <listitem open="0" type="815" id="104" />
+ <listitem open="0" type="815" id="87" />
+ <listitem open="0" type="815" id="98" />
+ <listitem open="0" type="815" id="90" />
+ <listitem open="0" type="815" id="95" />
+ </listitem>
+ <listitem open="0" type="830" id="-1" label="Datatypes" >
+ <listitem open="1" type="829" id="84" />
+ <listitem open="1" type="829" id="94" />
+ <listitem open="1" type="829" id="86" />
+ <listitem open="1" type="829" id="5" />
+ <listitem open="1" type="829" id="4" />
+ <listitem open="1" type="829" id="7" />
+ <listitem open="1" type="829" id="6" />
+ <listitem open="1" type="829" id="2" />
+ <listitem open="1" type="829" id="8" />
+ <listitem open="1" type="829" id="9" />
+ <listitem open="1" type="829" id="10" />
+ </listitem>
+ </listitem>
+ <listitem open="1" type="802" id="-1" label="Use Case View" />
+ <listitem open="1" type="821" id="-1" label="Component View" />
+ <listitem open="1" type="827" id="-1" label="Deployment View" />
+ </listitem>
+ </listview>
+ <codegeneration/>
+ </XMI.extensions>
+</XMI>
diff --git a/kpilot/conduits/memofileconduit/memofiles.cc b/kpilot/conduits/memofileconduit/memofiles.cc
new file mode 100644
index 000000000..2846d448b
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofiles.cc
@@ -0,0 +1,700 @@
+/* memofile-conduit.cc KPilot
+**
+** Copyright (C) 2004-2007 by 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 "memofiles.h"
+#include "memofile.h"
+
+QString Memofiles::FIELD_SEP = CSL1("\t");
+
+Memofiles::Memofiles (MemoCategoryMap & categories, PilotMemoInfo &appInfo,
+ QString & baseDirectory, CUDCounter &fCtrPC) :
+ _categories(categories), _memoAppInfo(appInfo),
+ _baseDirectory(baseDirectory), _cudCounter(fCtrPC)
+{
+ FUNCTIONSETUP;
+ _memofiles.clear();
+ _memoMetadataFile = _baseDirectory + QDir::separator() + CSL1(".ids");
+ _categoryMetadataFile = _baseDirectory + QDir::separator() + CSL1(".categories");
+ _memofiles.setAutoDelete(true);
+
+ _ready = ensureDirectoryReady();
+
+ _metadataLoaded = loadFromMetadata();
+}
+
+Memofiles::~Memofiles()
+{
+ FUNCTIONSETUP;
+}
+
+void Memofiles::load (bool loadAll)
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname
+ << ": now looking at all memofiles in your directory." << endl;
+
+ // now go through each of our known categories and look in each directory
+ // for that category for memo files
+ MemoCategoryMap::ConstIterator it;
+ int counter = -1;
+
+ for ( it = _categories.begin(); it != _categories.end(); ++it ) {
+ int category = it.key();
+ QString categoryName = it.data();
+ QString categoryDirname = _baseDirectory + QDir::separator() + categoryName;
+
+ QDir dir = QDir(categoryDirname);
+ if (! dir.exists() ) {
+ DEBUGKPILOT << fname
+ << ": category directory: [" << categoryDirname
+ << "] doesn't exist. skipping." << endl;
+ continue;
+ }
+
+
+ QStringList entries = dir.entryList(QDir::Files);
+ QString file;
+ for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) {
+ file = *it;
+ QFileInfo info(dir, file);
+
+ if(info.isFile() && info.isReadable()) {
+// DEBUGKPILOT << fname
+// << ": checking category: [" << categoryName
+// << "], file: [" << file << "]." << endl;
+ Memofile * memofile = find(categoryName, file);
+ if (NULL == memofile) {
+ memofile = new Memofile(category, categoryName, file, _baseDirectory);
+ memofile->setModified(true);
+ _memofiles.append(memofile);
+ DEBUGKPILOT << fname
+ << ": looks like we didn't know about this one until now. "
+ << "created new memofile for category: ["
+ << categoryName << "], file: [" << file << "]." << endl;
+
+ }
+
+ counter++;
+
+ // okay, we should have a memofile for this file now. see if we need
+ // to load its text...
+ if (memofile->isModified() || loadAll) {
+ DEBUGKPILOT << fname
+ << ": now loading text for: [" << info.filePath() << "]." << endl;
+ memofile->load();
+ }
+ } else {
+ DEBUGKPILOT << fname
+ << ": couldn't read file: [" << info.filePath() << "]. skipping it." << endl;
+
+ }
+ } // end of iterating through files in this directory
+
+ } // end of iterating through our categories/directories
+
+ DEBUGKPILOT << fname
+ << ": looked at: [" << counter << "] files from your directories." << endl;
+
+
+ // okay, now we've loaded everything from our directories. make one last
+ // pass through our loaded memofiles and see if we need to mark any of them
+ // as deleted (i.e. we created a memofile object from our metadata, but
+ // the file is now gone, so it's deleted.
+ Memofile * memofile;
+
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ if (! memofile->fileExists()) {
+ memofile->setDeleted( true );
+ }
+ }
+}
+
+/**
+* Make sure that our directory is ready to synchronize with our
+* Palm's database. This means we need to make sure that the directory
+* that our user has specified for storing his/her memos exists, as well
+* as a directory inside that directory for each of his/her memo categories.
+*/
+bool Memofiles::ensureDirectoryReady()
+{
+ FUNCTIONSETUP;
+
+ if (!checkDirectory(_baseDirectory))
+ return false;
+
+ int failures = 0;
+ // now make sure that a directory for each category exists.
+ QString _category_name;
+ QString dir;
+
+ MemoCategoryMap::Iterator it;
+ for ( it = _categories.begin(); it != _categories.end(); ++it ) {
+ _category_name = it.data();
+ dir = _baseDirectory + QDir::separator() + _category_name;
+
+ DEBUGKPILOT << fname
+ << ": checking directory: [" << dir << "]" << endl;
+
+ if (!checkDirectory(dir))
+ failures++;
+ }
+
+ return failures == 0;
+}
+
+bool Memofiles::checkDirectory(QString & dir)
+{
+ FUNCTIONSETUP;
+ // make sure that the directory we're asked to write to exists
+ QDir d(dir);
+ QFileInfo fid( dir );
+
+ if ( ! fid.isDir() ) {
+
+ DEBUGKPILOT << fname
+ << ": directory: [" << dir
+ << "] doesn't exist. creating...."
+ << endl;
+
+ if (!d.mkdir(dir)) {
+
+ DEBUGKPILOT << fname
+ << ": could not create directory: [" << dir
+ << "]. this won't end well." << endl;
+ return false;
+ } else {
+ DEBUGKPILOT << fname
+ << ": directory created: ["
+ << dir << "]." << endl;
+
+ }
+ } else {
+ DEBUGKPILOT << fname
+ << ": directory already existed: ["
+ << dir << "]." << endl;
+
+ }
+
+ return true;
+
+}
+
+void Memofiles::eraseLocalMemos ()
+{
+ FUNCTIONSETUP;
+
+ MemoCategoryMap::Iterator it;
+ for ( it = _categories.begin(); it != _categories.end(); ++it ) {
+ QString dir = _baseDirectory + QDir::separator() + it.data();
+
+ if (!folderRemove(QDir(dir))) {
+ DEBUGKPILOT << fname
+ << ": couldn't erase all local memos from: ["
+ << dir << "]." << endl;
+ }
+ }
+ QDir d(_baseDirectory);
+ d.remove(_memoMetadataFile);
+
+ ensureDirectoryReady();
+
+ _memofiles.clear();
+}
+
+void Memofiles::setPilotMemos (QPtrList<PilotMemo> & memos)
+{
+ FUNCTIONSETUP;
+
+ PilotMemo * memo;
+
+ _memofiles.clear();
+
+ for ( memo = memos.first(); memo; memo = memos.next() ) {
+ addModifiedMemo(memo);
+ }
+
+ DEBUGKPILOT << fname
+ << ": set: ["
+ << _memofiles.count() << "] from Palm to local." << endl;
+
+}
+
+bool Memofiles::loadFromMetadata ()
+{
+ FUNCTIONSETUP;
+
+ _memofiles.clear();
+
+ QFile f( _memoMetadataFile );
+ if ( !f.open( IO_ReadOnly ) ) {
+ DEBUGKPILOT << fname
+ << ": ooh, bad. couldn't open your memo-id file for reading."
+ << endl;
+ return false;
+ }
+
+ QTextStream t( &f );
+ Memofile * memofile;
+
+ while ( !t.atEnd() ) {
+ QString data = t.readLine();
+ int errors = 0;
+ bool ok;
+
+ QStringList fields = QStringList::split( FIELD_SEP, data );
+ if ( fields.count() >= 4 ) {
+ int id = fields[0].toInt( &ok );
+ if ( !ok )
+ errors++;
+ int category = fields[1].toInt( &ok );
+ if ( !ok )
+ errors++;
+ uint lastModified = fields[2].toInt( &ok );
+ if ( !ok )
+ errors++;
+ uint size = fields[3].toInt( &ok );
+ if ( !ok )
+ errors++;
+ QString filename = fields[4];
+ if ( filename.isEmpty() )
+ errors++;
+
+ if (errors <= 0) {
+ memofile = new Memofile(id, category, lastModified, size,
+ _categories[category], filename, _baseDirectory);
+ _memofiles.append(memofile);
+ // DEBUGKPILOT << fname
+ // << ": created memofile from metadata. id: [" << id
+ // << "], category: ["
+ // << _categories[category] << "], filename: [" << filename << "]."
+ // << endl;
+ }
+ } else {
+ errors++;
+ }
+
+ if (errors > 0) {
+ DEBUGKPILOT << fname
+ << ": error: couldn't understand this line: [" << data << "]."
+ << endl;
+ }
+ }
+
+ DEBUGKPILOT << fname
+ << ": loaded: [" << _memofiles.count() << "] memofiles."
+ << endl;
+
+ f.close();
+
+ return true;
+}
+
+Memofile * Memofiles::find (recordid_t id)
+{
+
+ Memofile * memofile;
+
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ if ( memofile->id() == id) {
+ return memofile;
+ }
+ }
+
+ return NULL;
+
+}
+
+Memofile * Memofiles::find (const QString & category, const QString & filename)
+{
+
+ Memofile * memofile;
+
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ if ( memofile->getCategoryName() == category &&
+ memofile->getFilename() == filename ) {
+ return memofile;
+ }
+ }
+
+ return NULL;
+
+}
+
+void Memofiles::deleteMemo(PilotMemo * memo)
+{
+ FUNCTIONSETUP;
+ if (! memo->isDeleted())
+ return;
+
+ Memofile * memofile = find(memo->id());
+ if (memofile) {
+ memofile->deleteFile();
+ _memofiles.remove(memofile);
+ _cudCounter.deleted();
+ }
+}
+
+
+void Memofiles::addModifiedMemo (PilotMemo * memo)
+{
+ FUNCTIONSETUP;
+
+ if (memo->isDeleted()) {
+ deleteMemo(memo);
+ return;
+ }
+
+ QString debug = CSL1(": adding a PilotMemo. id: [")
+ + QString::number(memo->id()) + CSL1("], title: [")
+ + memo->getTitle() + CSL1("]. ");
+
+ Memofile * memofile = find(memo->id());
+
+ if (NULL == memofile) {
+ _cudCounter.created();
+ debug += CSL1(" new from pilot.");
+ } else {
+ // we have found a local memofile that was modified on the palm. for the time
+ // being (until someone complains, etc.), we will always overwrite changes to
+ // the local filesystem with changes to the palm (palm overrides local). at
+ // some point in the future, we should probably honor a user preference for
+ // this...
+ _cudCounter.updated();
+ _memofiles.remove(memofile);
+ debug += CSL1(" modified from pilot.");
+ }
+
+ DEBUGKPILOT << fname
+ << debug << endl;
+
+ memofile = new Memofile(memo, _categories[memo->category()], filename(memo), _baseDirectory);
+ memofile->setModifiedByPalm(true);
+ _memofiles.append(memofile);
+
+}
+
+QPtrList<Memofile> Memofiles::getModified ()
+{
+ FUNCTIONSETUP;
+
+ QPtrList<Memofile> modList;
+ modList.clear();
+
+ Memofile * memofile;
+
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ if ( memofile->isModified() && ! memofile->isModifiedByPalm() ) {
+ modList.append(memofile);
+ }
+ }
+
+ DEBUGKPILOT << fname
+ << ": found: [" << modList.count() << "] memofiles modified on filesystem." << endl;
+
+ return modList;
+}
+
+void Memofiles::save()
+{
+ FUNCTIONSETUP;
+
+ saveCategoryMetadata();
+ saveMemos();
+ // this needs to be done last, because saveMemos() might change
+ // attributes of the Memofiles
+ saveMemoMetadata();
+
+}
+
+bool Memofiles::saveMemoMetadata()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname
+ << ": saving memo metadata to file: ["
+ << _memoMetadataFile << "]" << endl;
+
+ QFile f( _memoMetadataFile );
+ QTextStream stream(&f);
+
+ if( !f.open(IO_WriteOnly) ) {
+ DEBUGKPILOT << fname
+ << ": ooh, bad. couldn't open your memo-id file for writing."
+ << endl;
+ return false;
+ }
+
+ Memofile * memofile;
+
+ // each line looks like this, but FIELD_SEP is the separator instead of ","
+ // id,category,lastModifiedTime,filesize,filename
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ // don't save deleted memos to our id file
+ if (! memofile->isDeleted()) {
+ stream << memofile->id() << FIELD_SEP
+ << memofile->category() << FIELD_SEP
+ << memofile->lastModified() << FIELD_SEP
+ << memofile->size() << FIELD_SEP
+ << memofile->filename()
+ << endl;
+ }
+ }
+
+ f.close();
+
+ return true;
+
+}
+
+MemoCategoryMap Memofiles::readCategoryMetadata()
+{
+ FUNCTIONSETUP;
+
+ DEBUGKPILOT << fname
+ << ": reading categories from file: ["
+ << _categoryMetadataFile << "]" << endl;
+
+ MemoCategoryMap map;
+ map.clear();
+
+ QFile f( _categoryMetadataFile );
+ QTextStream stream(&f);
+
+ if( !f.open(IO_ReadOnly) ) {
+ DEBUGKPILOT << fname
+ << ": ooh, bad. couldn't open your categories file for reading."
+ << endl;
+ return map;
+ }
+
+
+ while ( !stream.atEnd() ) {
+ QString data = stream.readLine();
+ int errors = 0;
+ bool ok;
+
+ QStringList fields = QStringList::split( FIELD_SEP, data );
+ if ( fields.count() >= 2 ) {
+ int id = fields[0].toInt( &ok );
+ if ( !ok )
+ errors++;
+ QString categoryName = fields[1];
+ if ( categoryName.isEmpty() )
+ errors++;
+
+ if (errors <= 0) {
+ map[id] = categoryName;
+ }
+ } else {
+ errors++;
+ }
+
+ if (errors > 0) {
+ DEBUGKPILOT << fname
+ << ": error: couldn't understand this line: [" << data << "]."
+ << endl;
+ }
+ }
+
+ DEBUGKPILOT << fname
+ << ": loaded: [" << map.count() << "] categories."
+ << endl;
+
+ f.close();
+
+ return map;
+}
+
+bool Memofiles::saveCategoryMetadata()
+{
+ FUNCTIONSETUP;
+
+
+ DEBUGKPILOT << fname
+ << ": saving categories to file: ["
+ << _categoryMetadataFile << "]" << endl;
+
+ QFile f( _categoryMetadataFile );
+ QTextStream stream(&f);
+
+ if( !f.open(IO_WriteOnly) ) {
+ DEBUGKPILOT << fname
+ << ": ooh, bad. couldn't open your categories file for writing."
+ << endl;
+ return false;
+ }
+
+ MemoCategoryMap::Iterator it;
+ for ( it = _categories.begin(); it != _categories.end(); ++it ) {
+ stream << it.key()
+ << FIELD_SEP
+ << it.data()
+ << endl;
+ }
+
+ f.close();
+
+ return true;
+}
+
+bool Memofiles::saveMemos()
+{
+ FUNCTIONSETUP;
+
+ Memofile * memofile;
+ bool result = true;
+
+ for ( memofile = _memofiles.first(); memofile; memofile = _memofiles.next() ) {
+ if (memofile->isDeleted()) {
+ _memofiles.remove(memofile);
+ } else {
+ result = memofile->save();
+ // Fix prompted by Bug #103922
+ // if we weren't able to save the file, then remove it from the list.
+ // if we don't do this, the next sync will think that the user deliberately
+ // deleted the memofile and will then delete it from the Pilot.
+ // TODO -- at some point, we should probably tell the user that this
+ // did not work, but that will require a String change.
+ // Also, this is a partial fix since at this point
+ // this memo will never make its way onto the PC, but at least
+ // we won't delete it from the Pilot erroneously either. *sigh*
+ if (!result) {
+ DEBUGKPILOT << fname
+ << ": unable to save memofile: ["
+ << memofile->filename()
+ << "], now removing it from the metadata list."
+ << endl;
+ _memofiles.remove(memofile);
+ }
+ }
+ }
+ return true;
+}
+
+bool Memofiles::isFirstSync()
+{
+ FUNCTIONSETUP;
+ bool metadataExists = QFile::exists(_memoMetadataFile) &&
+ QFile::exists(_categoryMetadataFile);
+
+ bool valid = metadataExists && _metadataLoaded;
+
+ DEBUGKPILOT << fname
+ << ": local metadata exists: [" << metadataExists
+ << "], metadata loaded: [" << _metadataLoaded
+ << "], returning: [" << ! valid << "]" << endl;
+ return ! valid;
+}
+
+
+
+bool Memofiles::folderRemove(const QDir &_d)
+{
+ FUNCTIONSETUP;
+
+ QDir d = _d;
+
+ QStringList entries = d.entryList();
+ for(QStringList::Iterator it = entries.begin(); it != entries.end(); ++it) {
+ if(*it == CSL1(".") || *it == CSL1(".."))
+ continue;
+ QFileInfo info(d, *it);
+ if(info.isDir()) {
+ if(!folderRemove(QDir(info.filePath())))
+ return FALSE;
+ } else {
+ DEBUGKPILOT << fname
+ << ": deleting file: [" << info.filePath() << "]" << endl;
+ d.remove(info.filePath());
+ }
+ }
+ QString name = d.dirName();
+ if(!d.cdUp())
+ return FALSE;
+ DEBUGKPILOT << fname
+ << ": removing folder: [" << name << "]" << endl;
+ d.rmdir(name);
+
+ return TRUE;
+}
+
+QString Memofiles::filename(PilotMemo * memo)
+{
+ FUNCTIONSETUP;
+
+ QString filename = memo->getTitle();
+
+ if (filename.isEmpty()) {
+ QString text = memo->text();
+ int i = text.find(CSL1("\n"));
+ if (i > 1) {
+ filename = text.left(i);
+ }
+ if (filename.isEmpty()) {
+ filename = CSL1("empty");
+ }
+ }
+
+ filename = sanitizeName(filename);
+
+ QString category = _categories[memo->category()];
+
+ Memofile * memofile = find(category, filename);
+
+ // if we couldn't find a memofile with this filename, or if the
+ // memofile that is found is the same as the memo that we're looking
+ // at, then use the filename
+ if (NULL == memofile || memofile == memo) {
+ return filename;
+ }
+
+ int uniq = 2;
+ QString newfilename;
+
+ // try to find a good filename, but only do this 20 times at the most.
+ // if our user has 20 memos with the same filename, he/she is asking
+ // for trouble.
+ while (NULL != memofile && uniq <=20) {
+ newfilename = QString(filename + CSL1(".") + QString::number(uniq++) );
+ memofile = find(category, newfilename);
+ }
+
+ return newfilename;
+}
+
+QString Memofiles::sanitizeName(QString name)
+{
+ QString clean = name;
+ // safety net. we can't save a
+ // filesystem separator as part of a filename, now can we?
+ clean.replace('/', CSL1("-"));
+ return clean;
+}
+
diff --git a/kpilot/conduits/memofileconduit/memofiles.h b/kpilot/conduits/memofileconduit/memofiles.h
new file mode 100644
index 000000000..ec0497d5b
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/memofiles.h
@@ -0,0 +1,96 @@
+#ifndef _MEMOFILE_MEMOFILES_H
+#define _MEMOFILE_MEMOFILES_H
+/* memofiles.h KPilot
+**
+** Copyright (C) 2004-2007 by 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 "plugin.h"
+#include <qmap.h>
+
+#include "memofile.h"
+
+typedef QMap<int, QString> MemoCategoryMap;
+
+class Memofile;
+
+class Memofiles {
+
+public:
+
+ Memofiles (MemoCategoryMap & categories, PilotMemoInfo &appInfo,
+ QString & baseDirectory, CUDCounter &fCtrHH);
+ ~Memofiles();
+
+ void load(bool loadAll);
+ void save();
+ void eraseLocalMemos();
+ void setPilotMemos (QPtrList<PilotMemo> & memos);
+ void addModifiedMemo (PilotMemo * memo);
+ void deleteMemo (PilotMemo * memo);
+
+ bool isFirstSync();
+ bool isReady() { return _ready; };
+
+ QPtrList<Memofile> getModified();
+ QPtrList<Memofile> getAll() { return _memofiles; } ;
+ Memofile * find (const QString & category, const QString & filename);
+ Memofile * find (recordid_t id);
+
+ MemoCategoryMap readCategoryMetadata();
+ void setCategories(MemoCategoryMap map) { _categories = map; } ;
+
+ static QString FIELD_SEP;
+ static QString sanitizeName(QString name);
+
+ int count() { return _memofiles.count(); }
+
+private:
+
+ MemoCategoryMap _categories;
+ PilotMemoInfo &_memoAppInfo;
+ QString & _baseDirectory;
+ CUDCounter &_cudCounter;
+ QPtrList<Memofile> _memofiles;
+
+ bool loadFromMetadata();
+ bool ensureDirectoryReady();
+ bool checkDirectory(QString & dir);
+ bool saveMemoMetadata();
+ bool saveCategoryMetadata();
+ bool saveMemos();
+ bool folderRemove(const QDir & dir);
+
+ QString filename(PilotMemo * memo);
+
+
+ QString _categoryMetadataFile;
+ QString _memoMetadataFile;
+
+ bool _metadataLoaded;
+ bool _ready;
+
+};
+#endif //MEMOFILES_H
+
diff --git a/kpilot/conduits/memofileconduit/setup_base.ui b/kpilot/conduits/memofileconduit/setup_base.ui
new file mode 100644
index 000000000..215c18057
--- /dev/null
+++ b/kpilot/conduits/memofileconduit/setup_base.ui
@@ -0,0 +1,143 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>MemofileWidget</class>
+<comment>A tabWidget for configuring
+the Memofile-conduit settings.</comment>
+<author>Jason 'vanRijn' Kasper</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form1</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>342</width>
+ <height>412</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="baseSize">
+ <size>
+ <width>570</width>
+ <height>270</height>
+ </size>
+ </property>
+ <property name="caption">
+ <string>Memofile Conduit Options</string>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <property name="layoutSpacing" stdset="0">
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="layoutMargin" stdset="0">
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>Widget2</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="2">
+ <property name="name">
+ <cstring>Spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>180</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Sync private records:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Memos directory:</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fDirectory</cstring>
+ </property>
+ <property name="mode">
+ <number>18</number>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Select the directory you want to store your PDA's memos in</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>fSyncPrivate</cstring>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>tabWidget</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+<includes>
+ <include location="global" impldecl="in implementation">kurlrequester.h</include>
+ <include location="global" impldecl="in implementation">klineedit.h</include>
+ <include location="global" impldecl="in implementation">kpushbutton.h</include>
+</includes>
+</UI>