From 460c52653ab0dcca6f19a4f492ed2c5e4e963ab0 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdepim@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kpilot/conduits/memofileconduit/CMakeLists.txt | 44 ++ kpilot/conduits/memofileconduit/Makefile.am | 16 + .../memofileconduit/design/SQD - copyHHToPC.jpg | Bin 0 -> 111060 bytes .../memofileconduit/design/SQD - copyPCToHH.jpg | Bin 0 -> 69573 bytes .../memofileconduit/design/SQD - detailed load.jpg | Bin 0 -> 119635 bytes .../conduits/memofileconduit/design/SQD - sync.jpg | Bin 0 -> 112438 bytes .../conduits/memofileconduit/memofile-conduit.cc | 567 +++++++++++++++++ .../memofileconduit/memofile-conduit.desktop | 93 +++ kpilot/conduits/memofileconduit/memofile-conduit.h | 92 +++ .../conduits/memofileconduit/memofile-factory.cc | 128 ++++ kpilot/conduits/memofileconduit/memofile-factory.h | 40 ++ kpilot/conduits/memofileconduit/memofile.cc | 239 +++++++ kpilot/conduits/memofileconduit/memofile.h | 113 ++++ .../memofileconduit/memofileSettings.kcfgc | 7 + .../conduits/memofileconduit/memofileconduit.kcfg | 16 + .../conduits/memofileconduit/memofileconduit.xmi | 241 +++++++ kpilot/conduits/memofileconduit/memofiles.cc | 700 +++++++++++++++++++++ kpilot/conduits/memofileconduit/memofiles.h | 96 +++ kpilot/conduits/memofileconduit/setup_base.ui | 143 +++++ 19 files changed, 2535 insertions(+) create mode 100644 kpilot/conduits/memofileconduit/CMakeLists.txt create mode 100644 kpilot/conduits/memofileconduit/Makefile.am create mode 100644 kpilot/conduits/memofileconduit/design/SQD - copyHHToPC.jpg create mode 100644 kpilot/conduits/memofileconduit/design/SQD - copyPCToHH.jpg create mode 100644 kpilot/conduits/memofileconduit/design/SQD - detailed load.jpg create mode 100644 kpilot/conduits/memofileconduit/design/SQD - sync.jpg create mode 100644 kpilot/conduits/memofileconduit/memofile-conduit.cc create mode 100644 kpilot/conduits/memofileconduit/memofile-conduit.desktop create mode 100644 kpilot/conduits/memofileconduit/memofile-conduit.h create mode 100644 kpilot/conduits/memofileconduit/memofile-factory.cc create mode 100644 kpilot/conduits/memofileconduit/memofile-factory.h create mode 100644 kpilot/conduits/memofileconduit/memofile.cc create mode 100644 kpilot/conduits/memofileconduit/memofile.h create mode 100644 kpilot/conduits/memofileconduit/memofileSettings.kcfgc create mode 100644 kpilot/conduits/memofileconduit/memofileconduit.kcfg create mode 100644 kpilot/conduits/memofileconduit/memofileconduit.xmi create mode 100644 kpilot/conduits/memofileconduit/memofiles.cc create mode 100644 kpilot/conduits/memofileconduit/memofiles.h create mode 100644 kpilot/conduits/memofileconduit/setup_base.ui (limited to 'kpilot/conduits/memofileconduit') 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 Binary files /dev/null and b/kpilot/conduits/memofileconduit/design/SQD - copyHHToPC.jpg 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 Binary files /dev/null and b/kpilot/conduits/memofileconduit/design/SQD - copyPCToHH.jpg 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 Binary files /dev/null and b/kpilot/conduits/memofileconduit/design/SQD - detailed load.jpg 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 Binary files /dev/null and b/kpilot/conduits/memofileconduit/design/SQD - sync.jpg 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 // required by pilot-link includes + +#include + +#include "pilotMemo.h" + +#include +#include +#include + +#include +#include + +#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 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 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 + +#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 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 +#include +#include + +#include +#include +#include +#include + +#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(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 // required by pilot-link includes + +#include + +#include +#include +#include +#include + +#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 @@ + + + + + + + $HOME/MyMemos + + + + true + + + + + 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 @@ + + + + + umbrello uml modeller http://uml.sf.net + 1.2.90 + UnicodeUTF8 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 & 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 Memofiles::getModified () +{ + FUNCTIONSETUP; + + QPtrList 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 + +#include "memofile.h" + +typedef QMap 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 & memos); + void addModifiedMemo (PilotMemo * memo); + void deleteMemo (PilotMemo * memo); + + bool isFirstSync(); + bool isReady() { return _ready; }; + + QPtrList getModified(); + QPtrList 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 _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 @@ + +MemofileWidget +A tabWidget for configuring +the Memofile-conduit settings. +Jason 'vanRijn' Kasper + + + Form1 + + + + 0 + 0 + 342 + 412 + + + + + 5 + 5 + 0 + 0 + + + + + 570 + 270 + + + + Memofile Conduit Options + + + + + + + + unnamed + + + 0 + + + 6 + + + + tabWidget + + + + 7 + 7 + 0 + 0 + + + + + + + Widget2 + + + General + + + + unnamed + + + + Spacer4 + + + Vertical + + + Expanding + + + + 20 + 180 + + + + + + textLabel2 + + + Sync private records: + + + + + textLabel1 + + + Memos directory: + + + + + fDirectory + + + 18 + + + Select the directory you want to store your PDA's memos in + + + + + fSyncPrivate + + + + + + true + + + + + + + + + tabWidget + + + + kurlrequester.h + klineedit.h + kpushbutton.h + + -- cgit v1.2.1