summaryrefslogtreecommitdiffstats
path: root/kpilot/conduits/docconduit
diff options
context:
space:
mode:
Diffstat (limited to 'kpilot/conduits/docconduit')
-rw-r--r--kpilot/conduits/docconduit/CMakeLists.txt87
-rw-r--r--kpilot/conduits/docconduit/DOC-converter.cc631
-rw-r--r--kpilot/conduits/docconduit/DOC-converter.h183
-rw-r--r--kpilot/conduits/docconduit/Icons/CMakeLists.txt3
-rw-r--r--kpilot/conduits/docconduit/Icons/Makefile.am7
-rw-r--r--kpilot/conduits/docconduit/Icons/cr16-app-kpalmdoc.pngbin0 -> 747 bytes
-rw-r--r--kpilot/conduits/docconduit/Icons/cr22-app-kpalmdoc.pngbin0 -> 1088 bytes
-rw-r--r--kpilot/conduits/docconduit/Icons/cr32-app-kpalmdoc.pngbin0 -> 2007 bytes
-rw-r--r--kpilot/conduits/docconduit/Icons/cr48-app-kpalmdoc.pngbin0 -> 3254 bytes
-rw-r--r--kpilot/conduits/docconduit/Makefile.am38
-rw-r--r--kpilot/conduits/docconduit/bmkSpecification.txt199
-rw-r--r--kpilot/conduits/docconduit/doc-conduit.cc1018
-rw-r--r--kpilot/conduits/docconduit/doc-conduit.h152
-rw-r--r--kpilot/conduits/docconduit/doc-conflictdialog.cc182
-rw-r--r--kpilot/conduits/docconduit/doc-conflictdialog.h83
-rw-r--r--kpilot/conduits/docconduit/doc-factory.cc116
-rw-r--r--kpilot/conduits/docconduit/doc-factory.h74
-rw-r--r--kpilot/conduits/docconduit/doc-setup.cc136
-rw-r--r--kpilot/conduits/docconduit/doc-setup.h47
-rw-r--r--kpilot/conduits/docconduit/doc-setupdialog.ui557
-rw-r--r--kpilot/conduits/docconduit/doc_conduit.desktop59
-rw-r--r--kpilot/conduits/docconduit/docconduit.kcfg54
-rw-r--r--kpilot/conduits/docconduit/docconduitSettings.kcfgc7
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc.cpp58
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc.desktop65
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc.kcfg41
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc.upd6
-rw-r--r--kpilot/conduits/docconduit/kpalmdocSettings.kcfgc7
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc_dlg.cc529
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc_dlg.h67
-rw-r--r--kpilot/conduits/docconduit/kpalmdoc_dlgbase.ui435
-rw-r--r--kpilot/conduits/docconduit/makedoc9.cc405
-rw-r--r--kpilot/conduits/docconduit/makedoc9.h111
-rw-r--r--kpilot/conduits/docconduit/pilotDOCBookmark.cc87
-rw-r--r--kpilot/conduits/docconduit/pilotDOCBookmark.h51
-rw-r--r--kpilot/conduits/docconduit/pilotDOCEntry.cc92
-rw-r--r--kpilot/conduits/docconduit/pilotDOCEntry.h73
-rw-r--r--kpilot/conduits/docconduit/pilotDOCHead.cc101
-rw-r--r--kpilot/conduits/docconduit/pilotDOCHead.h62
-rw-r--r--kpilot/conduits/docconduit/tests/testcompress.cpp59
40 files changed, 5882 insertions, 0 deletions
diff --git a/kpilot/conduits/docconduit/CMakeLists.txt b/kpilot/conduits/docconduit/CMakeLists.txt
new file mode 100644
index 000000000..fa87eb0fb
--- /dev/null
+++ b/kpilot/conduits/docconduit/CMakeLists.txt
@@ -0,0 +1,87 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+)
+
+set(doc_shared_SRCS
+ makedoc9.cc
+ pilotDOCHead.cc
+ pilotDOCEntry.cc
+ pilotDOCBookmark.cc
+ DOC-converter.cc
+)
+
+set(conduit_doc_SRCS
+ ${doc_shared_SRCS}
+ kpalmdoc_dlg.cc
+ kpalmdoc.cpp
+ doc-factory.cc
+ doc-setup.cc
+ doc-conduit.cc
+ doc-conflictdialog.cc
+)
+
+set(conduit_doc_UIS
+ kpalmdoc_dlgbase.ui
+ doc-setupdialog.ui
+)
+
+set(conduit_doc_KCFGS
+ docconduitSettings.kcfgc
+ kpalmdocSettings.kcfgc
+)
+
+kde3_add_kcfg_files(conduit_doc_SRCS ${conduit_doc_KCFGS})
+kde3_add_ui_files(conduit_doc_SRCS ${conduit_doc_UIS})
+kde3_automoc(${conduit_doc_SRCS})
+add_library(conduit_doc SHARED ${conduit_doc_SRCS})
+
+kpilot_rpath(conduit_doc)
+
+set_target_properties(
+ conduit_doc PROPERTIES LOCATION ${KDE3_PLUGIN_INSTALL_DIR}
+ PREFIX ""
+)
+
+kde3_install_libtool_file(conduit_doc)
+
+install(
+ TARGETS conduit_doc
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+)
+
+set(kpalmdoc_SRCS
+ ${doc_shared_SRCS}
+ kpalmdoc_dlg.cc
+ kpalmdoc.cpp
+)
+kde3_add_kcfg_files(kpalmdoc_SRCS kpalmdocSettings.kcfgc)
+kde3_add_ui_files(kpalmdoc_SRCS kpalmdoc_dlgbase.ui)
+kde3_automoc(${kpalmdoc_SRCS})
+add_executable(kpalmdoc ${kpalmdoc_SRCS})
+target_link_libraries(kpalmdoc ${QT_LIBRARIES} kpilot kdeui kio)
+kpilot_rpath(kpalmdoc)
+
+install(
+ TARGETS kpalmdoc conduit_doc
+ LIBRARY DESTINATION ${KDE3_PLUGIN_INSTALL_DIR}
+ RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin
+)
+
+install(
+ FILES doc_conduit.desktop DESTINATION ${KDE3_SERVICES_DIR}
+)
+
+install(
+ FILES docconduit.kcfg kpalmdoc.kcfg DESTINATION ${KDE3_KCFG_DIR}
+)
+
+install(
+ FILES kpalmdoc.desktop DESTINATION ${KDE3_XDG_APPS_DIR}
+)
+
+install(
+ FILES kpalmdoc.upd
+ DESTINATION ${CMAKE_INSTALL_PREFIX}/share/apps/kconf_update
+)
+
+add_subdirectory(Icons)
diff --git a/kpilot/conduits/docconduit/DOC-converter.cc b/kpilot/conduits/docconduit/DOC-converter.cc
new file mode 100644
index 000000000..c8d7ac02d
--- /dev/null
+++ b/kpilot/conduits/docconduit/DOC-converter.cc
@@ -0,0 +1,631 @@
+/* KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+** The doc converter synchronizes text files on the PC with DOC databases on the Palm
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+
+#include "options.h"
+#include "DOC-converter.moc"
+
+#include <qdir.h>
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qsortedlist.h>
+
+#include <pilotDatabase.h>
+#include <pilotLocalDatabase.h>
+#include <pilotSerialDatabase.h>
+
+#include "pilotDOCHead.h"
+#include "pilotDOCEntry.h"
+#include "pilotDOCBookmark.h"
+
+
+
+#define min(a,b) (a<b)?(a):(b)
+
+
+
+/****************************************************************************************************
+ * various bookmark classes. Most important is the bmkList findMatches(QString) function,
+ * which needs to return a list of all bookmarks found for the given bookmark expression.
+ * A bookmark usually consists of a bookmark text and an offset into the text document.
+ ****************************************************************************************************/
+
+
+bool docBookmark::compare_pos=true;
+
+bool operator< ( const docBookmark &s1, const docBookmark &s2)
+{
+ if (docBookmark::compare_pos) { return s1.position<s2.position;}
+ else {return s2.bmkName<s2.bmkName;}
+}
+
+bool operator== ( const docBookmark &s1, const docBookmark &s2)
+{
+ return (s1.position==s2.position) && (s1.bmkName==s2.bmkName);
+}
+
+
+int docMatchBookmark::findMatches(QString doctext, bmkList &fBookmarks) {
+ FUNCTIONSETUP;
+// bmkList res;
+ int pos = 0, nr=0, found=0;
+#ifdef DEBUG
+ DEBUGKPILOT<<"Finding matches of "<<pattern<<endl;
+#endif
+
+ while (pos >= 0 && found<to) {
+ pos = doctext.find(pattern, pos);
+#ifdef DEBUG
+ DEBUGKPILOT<<"Result of search: pos="<<pos<<endl;
+#endif
+ if (pos >= 0)
+ {
+ ++found;
+ if (found>=from && found<=to) {
+ fBookmarks.append(new docBookmark(pattern, pos));
+ ++nr;
+
+ }
+ ++pos;
+ }
+ }
+ return nr;
+}
+
+
+
+int docRegExpBookmark::findMatches(QString doctext, bmkList &fBookmarks)
+{
+ FUNCTIONSETUP;
+// bmkList res;
+ QRegExp rx(pattern);
+ int pos = 0, nr=0, found=0;
+
+ while (pos>=0 && found<=to) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Searching for bookmark "<<pattern<<endl;
+#endif
+ pos=rx.search(doctext, pos);
+ if (pos > -1) {
+ ++found;
+ if (found>=from && found<to) {
+ if (capSubexpression>=0) {
+ fBookmarks.append(new docBookmark(/*bmkName.left(16)*/rx.cap(capSubexpression), pos));
+ } else {
+ // TODO: use the subexpressions from the regexp for the bmk name ($1..$9) (given as separate regexp)
+ QString bmkText(bmkName);
+ for (int i=0; i<=rx.numCaptures(); ++i) {
+ bmkText.replace(CSL1("$%1").arg(i), rx.cap(i));
+ bmkText.replace(CSL1("\\%1").arg(i), rx.cap(i));
+ }
+ fBookmarks.append(new docBookmark(bmkText.left(16), pos));
+ }
+ ++nr;
+ }
+ ++pos;
+ }
+ }
+ return nr;
+}
+
+
+
+
+
+
+
+
+/*********************************************************************
+ C O N S T R U C T O R
+ *********************************************************************/
+
+
+DOCConverter::DOCConverter(QObject *parent, const char *name):QObject(parent,name) {
+ FUNCTIONSETUP;
+ docdb=0L;
+ eSortBookmarks=eSortNone;
+ fBookmarks.setAutoDelete( TRUE );
+}
+
+
+
+DOCConverter::~DOCConverter() {
+ FUNCTIONSETUP;
+}
+
+
+
+
+
+/*********************************************************************
+ S Y N C S T R U C T U R E
+ *********************************************************************/
+
+
+
+void DOCConverter::setTXTpath(QString path, QString file) {
+ QDir dr(path);
+ QFileInfo pth(dr, file);
+ if (!file.isEmpty())
+ txtfilename = pth.absFilePath();
+}
+
+
+
+void DOCConverter::setTXTpath(QString filename) {
+ if (!filename.isEmpty()) txtfilename = filename;
+}
+
+
+
+void DOCConverter::setPDB(PilotDatabase * dbi) {
+ if (dbi) docdb = dbi;
+}
+
+
+
+QString DOCConverter::readText() {
+ FUNCTIONSETUP;
+ if (txtfilename.isEmpty()) return QString();
+ QFile docfile(txtfilename);
+ if (!docfile.open(IO_ReadOnly))
+ {
+ emit logError(i18n("Unable to open text file %1 for reading.").arg(txtfilename));
+ return QString();
+ }
+
+ QTextStream docstream(&docfile);
+
+ QString doc = docstream.read();
+ docfile.close();
+ return doc;
+}
+
+
+
+int DOCConverter::findBmkEndtags(QString &text, bmkList&fBmks) {
+ FUNCTIONSETUP;
+ // Start from the end of the text
+ int pos = text.length() - 1, nr=0;
+ bool doSearch=true;
+ while (pos >= 0/* && doSearch*/) {
+ DEBUGKPILOT<<"Current character is \'"<<text[pos].latin1()<<"\'"<<endl;
+ // skip whitespace until we reach a >
+ while (text[pos].isSpace() && pos >= 0) {
+ DEBUGKPILOT<<"Skipping whitespaces at the end of the file"<<endl;
+ pos--;
+ }
+ // every other character than a > is assumed to belong to the text, so there are no more bookmarks.
+ if (pos < 0 || text[pos] != '>') {
+ DEBUGKPILOT<<"Current character \'"<<text[pos].latin1()<<"\' at position "<<pos<<" is not and ending >. Finish searching for bookmarks."<<endl;
+
+ pos=-1;
+ break;
+ } else {
+ int endpos = pos;
+ doSearch=true;
+ DEBUGKPILOT<<"Found the ending >, now looking for the opening <"<<endl;
+
+ // Search for the opening <. There must not be a newline in the bookmark text.
+ while (doSearch && pos > 0) {
+// DEBUGKPILOT<<"pos="<<pos<<", char="<<text[pos].latin1()<<endl;
+ pos--;
+ if (text[pos] == '\n') {
+ DEBUGKPILOT<<"Found carriage return at position "<<pos<<" inside the bookmark text, assuming this is not a bookmark, and the text ends in a >"<<endl;
+ doSearch = false;
+ pos = -1;
+ break;
+ }
+ if (text[pos] == '<') {
+ fBmks.append(new docMatchBookmark(text.mid(pos + 1, endpos - pos - 1)));
+ ++nr;
+ DEBUGKPILOT<<"Found opening < at position "<<pos<<", bookmarktext ="<<text.mid(pos+1, endpos-pos-1)<<endl;
+ text.remove(pos, text.length());
+ pos--;
+ doSearch = false;
+ }
+ }
+ }
+ DEBUGKPILOT<<"Finished processing the next bookmark, current position: "<<pos<<endl;
+ }
+ return nr;
+}
+
+int DOCConverter::findBmkInline(QString &text, bmkList &fBmks) {
+ FUNCTIONSETUP;
+// bmkList res;
+ int nr=0;
+ QRegExp rx(CSL1("<\\*(.*)\\*>"));
+
+ rx.setMinimal(TRUE);
+ int pos = 0;
+ while (pos >= 0) {
+ pos = rx.search(text, pos);
+ if (pos >= 0) {
+ fBmks.append(new docBookmark(rx.cap(1), pos+1));
+ ++nr;
+ text = text.remove(pos, rx.matchedLength());
+ }
+ }
+ return nr;
+}
+
+int DOCConverter::findBmkFile(QString &, bmkList &fBmks) {
+ FUNCTIONSETUP;
+ int nr=0;
+
+ QString bmkfilename = txtfilename;
+ if (bmkfilename.endsWith(CSL1(".txt"))){
+ bmkfilename.remove(bmkfilename.length()-4, 4);
+ }
+ QString oldbmkfilename=bmkfilename;
+ bmkfilename+=CSL1(BMK_SUFFIX);
+ QFile bmkfile(bmkfilename);
+ if (!bmkfile.open(IO_ReadOnly)) {
+ bmkfilename=oldbmkfilename+CSL1(PDBBMK_SUFFIX);
+ bmkfile.setName(bmkfilename);
+ if (!bmkfile.open(IO_ReadOnly)) {
+ DEBUGKPILOT<<"Unable to open bookmarks file "<<bmkfilename<<" for reading the bookmarks of "<<docdb ->dbPathName()<<endl;
+ return 0;
+ }
+ }
+
+ DEBUGKPILOT<<"Bookmark file: "<<bmkfilename<<endl;
+
+ QTextStream bmkstream(&bmkfile);
+ QString line;
+ while ( !(line=bmkstream.readLine()).isEmpty() ) {
+ if (!line.isEmpty() && !line.startsWith(CSL1("#")) ) {
+ QStringList bmkinfo=QStringList::split(CSL1(","), line);
+ int fieldnr=bmkinfo.count();
+ // We use the same syntax for the entries as MakeDocJ bookmark files:
+ // <bookmark>,<string-to-search>,<bookmark-name-string>,<starting-bookmark>,<ending-bookmark>
+ // For an explanation see: http://home.kc.rr.com/krzysztow/PalmPilot/MakeDocJ/index.html
+ if (fieldnr>0){
+ DEBUGKPILOT<<"Working on bookmark \""<<line<<"\""<<endl;
+ docMatchBookmark*bmk=0L;
+ QString bookmark=bmkinfo[0];
+ bool ok;
+ int pos=bookmark.toInt(&ok);
+ if (ok) {
+ if (fieldnr>1) {
+ QString name(bmkinfo[1]);
+ DEBUGKPILOT<<"Bookmark \""<<name<<"\" set at position "<<pos<<endl;
+ fBmks.append(new docBookmark(name, pos));
+ }
+ } else if (bookmark==CSL1("-") || bookmark==CSL1("+")) {
+ if (fieldnr>1) {
+ QString patt(bmkinfo[1]);
+ QString name(patt);
+ if (fieldnr>2) {
+ int cap=bmkinfo[2].toInt(&ok);
+ if (ok) {
+ bmk=new docRegExpBookmark(patt, cap);
+ } else {
+ name=bmkinfo[2];
+ bmk=new docRegExpBookmark(patt, name);
+ }
+ } else{
+ bmk=new docRegExpBookmark(patt, name);
+ }
+ // The third entry in the line (optional) denotes the index of a capture subexpression (if an integer) or the bookmark text as regexp (if a string)
+ DEBUGKPILOT<<"RegExp Bookmark, pattern="<<patt<<", name="<<name<<endl;
+ if (bmk) {
+ if (bookmark==CSL1("-")) {
+ bmk->from=1;
+ bmk->to=1;
+ } else {
+ if (fieldnr>3) {
+ bool ok;
+ int tmp=bmkinfo[3].toInt(&ok);
+ if (ok) bmk->from=tmp;
+ if (fieldnr>4) {
+ tmp=bmkinfo[4].toInt(&ok);
+ if (ok) bmk->to=tmp;
+ }
+ }
+ }
+ fBmks.append(bmk);
+ bmk=0L;
+ } else {
+ DEBUGKPILOT<<"Could not allocate bookmark "<<name<<endl;
+ }
+ } else {
+ DEBUGKPILOT<<"RegExp bookmark found with no other information (no bookmark pattern nor name)"<<endl;
+ }
+ } else {
+ QString pattern(bookmark);
+ if (fieldnr>1) pattern=bmkinfo[1];
+ if (fieldnr>2) bookmark=bmkinfo[2];
+ DEBUGKPILOT<<"RegExp Bookmark, pattern="<<pattern<<", name="<<bookmark<<endl;
+ bmk=new docRegExpBookmark(pattern, bookmark);
+ if (bmk) {
+ bmk->from=1;
+ bmk->to=1;
+ fBmks.append(bmk);
+ }
+ }
+ } // fieldnr>0
+ } // !line.isEmpty()
+ } // while
+ return nr;
+}
+
+bool DOCConverter::convertTXTtoPDB() {
+ FUNCTIONSETUP;
+
+ if (!docdb) {
+ emit logError(i18n("Unable to open Database for writing"));
+ return false;
+ }
+
+ QString text = readText();
+
+ if (fBmkTypes & eBmkEndtags) {
+ findBmkEndtags(text, fBookmarks);
+ } // end: EndTag Bookmarks
+
+
+ // Search for all tags <* Bookmark text *> in the text. We have to delete them immediately, otherwise the later bookmarks will be off.
+ if (fBmkTypes & eBmkInline) {
+ findBmkInline(text, fBookmarks);
+ } // end: Inline Bookmarks
+
+
+ // Read in regular expressions and positions from an external file (doc-filename with extension .bmk)
+ if (fBmkTypes & eBmkFile)
+ {
+ findBmkFile(text, fBookmarks);
+ }
+
+ // Process the bookmarks: find the occurrences of the regexps, and sort them if requested:
+ bmkSortedList pdbBookmarks;
+ pdbBookmarks.setAutoDelete(TRUE);
+ docBookmark*bmk;
+ for (bmk = fBookmarks.first(); bmk; bmk = fBookmarks.next())
+ {
+ bmk->findMatches(text, pdbBookmarks);
+ }
+
+ switch (eSortBookmarks)
+ {
+ case eSortName:
+ docBookmark::compare_pos=false;
+// qHeapSort(pdbBookmarks);
+ pdbBookmarks.sort();
+ break;
+ case eSortPos:
+ docBookmark::compare_pos=true;
+ pdbBookmarks.sort();
+ break;
+ case eSortNone:
+ default:
+ break;
+ }
+
+#ifdef DEBUG
+ DEBUGKPILOT << "Bookmarks: "<<endl;
+ for (bmk = pdbBookmarks.first(); bmk; bmk = pdbBookmarks.next())
+ {
+ DEBUGKPILOT<<bmk->bmkName.left(20)<<" at position "<<bmk->position<<endl;
+ }
+#endif
+
+ if (!docdb->isOpen()) {
+ emit logError(i18n("Unable to open palm doc database %1").arg(docdb->dbPathName()) );
+ return false;
+ }
+
+ // Clean the whole database, otherwise the records would be just appended!
+ docdb->deleteRecord(0, true);
+
+ // Header record for the doc file format
+ PilotDOCHead docHead;
+ docHead.position=0;
+ docHead.recordSize=4096;
+ docHead.spare=0;
+ docHead.storyLen=text.length();
+ docHead.version=compress?DOC_COMPRESSED:DOC_UNCOMPRESSED;
+ docHead.numRecords=(int)( (text.length()-1)/docHead.recordSize)+1;
+ PilotRecord*rec=docHead.pack();
+ docdb->writeRecord(rec);
+ KPILOT_DELETE(rec);
+
+ DEBUGKPILOT << "Write header record: length="<<text.length()<<", compress="<<compress<<endl;
+
+ // First compress the text, then write out the bookmarks and - if existing - also the annotations
+ int len=text.length();
+ int start=0,reclen=0;
+ int recnum=0;
+ while (start<len)
+ {
+ reclen=min(len-start, PilotDOCEntry::TEXT_SIZE);
+ DEBUGKPILOT << "Record #"<<recnum<<", reclen="<<reclen<<", compress="<<compress<<endl;
+
+ PilotDOCEntry recText;
+// recText.setText(text.mid(start, reclen), reclen);
+ recText.setText(text.mid(start, reclen));
+// if (compress)
+ recText.setCompress(compress);
+ PilotRecord*textRec=recText.pack();
+ docdb->writeRecord(textRec);
+ ++recnum;
+ start+=reclen;
+ KPILOT_DELETE(textRec);
+ }
+
+ recnum=0;
+ // Finally, write out the bookmarks
+ for (bmk = pdbBookmarks.first(); bmk; bmk = pdbBookmarks.next())
+// for (bmkList::const_iterator it=pdbBookmarks.begin(); it!=pdbBookmarks.end(); ++it)
+ {
+ ++recnum;
+ DEBUGKPILOT << "Bookmark #"<<recnum<<", Name="<<bmk->bmkName.left(20)<<", Position="<<bmk->position<<endl;
+
+ PilotDOCBookmark bmkEntry;
+ bmkEntry.pos=bmk->position;
+ strncpy(&bmkEntry.bookmarkName[0], bmk->bmkName.latin1(), 16);
+ PilotRecord*bmkRecord=bmkEntry.pack();
+ docdb->writeRecord(bmkRecord);
+ KPILOT_DELETE(bmkRecord);
+ }
+
+ pdbBookmarks.clear();
+ fBookmarks.clear();
+
+ return true;
+}
+
+
+
+bool DOCConverter::convertPDBtoTXT()
+{
+ FUNCTIONSETUP;
+ if (txtfilename.isEmpty()) {
+ emit logError(i18n("No filename set for the conversion"));
+ return false;
+ }
+
+ if (!docdb) {
+ emit logError(i18n("Unable to open Database for reading"));
+ return false;
+ }
+
+ // The first record of the db is the document header containing information about the doc db
+ PilotRecord*headerRec = docdb->readRecordByIndex(0);
+ if (!headerRec)
+ {
+ emit logError(i18n("Unable to read database header for database %1.").arg(docdb->dbPathName()));
+ KPILOT_DELETE(docdb);
+ return false;
+ }
+ PilotDOCHead header(headerRec);
+ KPILOT_DELETE(headerRec);
+
+ DEBUGKPILOT<<"Database "<<docdb->dbPathName()<<" has "<<header.numRecords<<" text records, "<<endl
+ <<" total number of records: "<<docdb->recordCount()<<endl
+ <<" position="<<header.position<<endl
+ <<" recordSize="<<header.recordSize<<endl
+ <<" spare="<<header.spare<<endl
+ <<" storyLen="<<header.storyLen<<endl
+// <<" textRecordSize="<<header.textRecordSize<<endl
+ <<" version="<<header.version<<endl;
+
+ // next come the header.numRecords real document records (might be compressed, see the version flag in the header)
+ QFile docfile(txtfilename);
+ if (!docfile.open(IO_WriteOnly))
+ {
+ emit logError(i18n("Unable to open output file %1.").arg(txtfilename));
+ KPILOT_DELETE(docdb);
+ return false;
+ }
+ QString doctext;
+ for (int i=1; i<header.numRecords+1; ++i)
+ {
+ PilotRecord*rec=docdb->readRecordByIndex(i);
+ if (rec)
+ {
+ PilotDOCEntry recText(rec, header.version==DOC_COMPRESSED);
+ doctext.append(recText.getText());
+ DEBUGKPILOT<<"Record "<<i<<endl;
+ KPILOT_DELETE(rec);
+ } else {
+ emit logMessage(i18n("Could not read text record #%1 from Database %2").arg(i).arg(docdb->dbPathName()));
+ }
+ }
+
+ // After the document records possibly come a few bookmark records, so read them in and put them in a separate bookmark file.
+ // for the ztxt conduit there might be annotations after the bookmarks, so the upper bound needs to be adapted.
+ int upperBmkRec=docdb->recordCount();
+ bmkSortedList bmks;
+ bmks.setAutoDelete(TRUE);
+ for (int i=header.numRecords+1; i<upperBmkRec; ++i)
+ {
+ PilotRecord*rec=docdb->readRecordByIndex(i);
+ if (rec)
+ {
+ PilotDOCBookmark bookie(rec);
+ docBookmark*bmk=new docBookmark(QString::fromLatin1(bookie.bookmarkName), bookie.pos);
+ bmks.append(bmk);
+ KPILOT_DELETE(rec);
+ } else {
+ emit logMessage(i18n("Could not read bookmark record #%1 from Database %2").arg(i).arg(docdb->dbPathName()));
+ }
+ }
+ // TODO: Sort the list of bookmarks according to their position
+ docBookmark::compare_pos=true;
+ bmks.sort();
+
+ if ((fBmkTypes & eBmkFile) && (bmks.count()>0))
+ {
+ QString bmkfilename = docfile.name();
+ if (bmkfilename.endsWith(CSL1(".txt"))){
+ bmkfilename.remove(bmkfilename.length()-4, 4);
+ }
+ bmkfilename+=CSL1(PDBBMK_SUFFIX);
+ QFile bmkfile(bmkfilename);
+ if (!bmkfile.open(IO_WriteOnly))
+ {
+ emit logError(i18n("Unable to open file %1 for the bookmarks of %2.")
+ .arg(bmkfilename).arg(docdb ->dbPathName()));
+ }
+ else
+ {
+ DEBUGKPILOT<<"Writing "<<upperBmkRec-header.numRecords<<
+ "("<<upperBmkRec<<") bookmarks to file "<<bmkfilename<<endl;
+ QTextStream bmkstream(&bmkfile);
+ for (docBookmark*bmk=bmks.first(); bmk; bmk=bmks.next())
+ {
+ bmkstream<<bmk->position<<", "<<bmk->bmkName<<endl;
+ }
+ //bmkstream.close();
+ bmkfile.close();
+ }
+ }
+ if (fBmkTypes & eBmkInline)
+ {
+ for (docBookmark*bmk=bmks.last(); bmk; bmk=bmks.prev())
+ {
+ doctext.insert(bmk->position, QString(CSL1("<*") +
+ bmk->bmkName +
+ CSL1("*>")));
+ }
+ }
+
+ // Finally, write the actual text out to the file.
+ QTextStream docstream(&docfile);
+ docstream<<doctext;
+ //docstream.close();
+ docfile.close();
+ docdb->cleanup();
+ // reset all records to unchanged. I don't know if this is really such a wise idea?
+ docdb->resetSyncFlags();
+ return true;
+}
+
+
diff --git a/kpilot/conduits/docconduit/DOC-converter.h b/kpilot/conduits/docconduit/DOC-converter.h
new file mode 100644
index 000000000..f3747ea1d
--- /dev/null
+++ b/kpilot/conduits/docconduit/DOC-converter.h
@@ -0,0 +1,183 @@
+#ifndef _DOC_CONVERTER_H
+#define _DOC_CONVERTER_H
+/* DOC-converter.h KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+
+
+#define DOC_UNCOMPRESSED 1
+#define DOC_COMPRESSED 2
+
+
+#define BMK_SUFFIX ".bmk"
+#define PDBBMK_SUFFIX ".bm"
+
+#include <qptrlist.h>
+#include <qobject.h>
+
+class PilotDatabase;
+
+
+/****************************************************************************************************
+ * various bookmark classes. Most important is the bmkList findMatches(QString, bmkList &) function,
+ * which needs to return a list of all bookmarks found for the given bookmark expression.
+ * A bookmark usually consists of a bookmark text and an offset into the text document.
+ ****************************************************************************************************/
+
+class docBookmark;
+#define bmkList QPtrList<docBookmark>
+#define bmkSortedList QSortedList<docBookmark>
+
+class docBookmark {
+public:
+ static bool compare_pos;
+ docBookmark():bmkName(), position(0) { };
+ docBookmark(QString name, long int pos):bmkName(name), position(pos) { };
+ docBookmark(const docBookmark &bmk):bmkName(bmk.bmkName),position(bmk.position){};
+ virtual ~ docBookmark() { };
+ virtual int findMatches(QString, bmkList &fBookmarks) {
+ FUNCTIONSETUP;
+ fBookmarks.append(new docBookmark(*this));
+ return 1;
+ };
+
+ QString bmkName;
+ long int position;
+};
+
+class docMatchBookmark:public docBookmark {
+ public:
+ docMatchBookmark():docBookmark() { from=0; to=100;};
+ docMatchBookmark(QString pattrn, int options=0):docBookmark(),
+ pattern(pattrn), opts(options) { from=0; to=100; };
+ docMatchBookmark(QString pattrn, QString bmkname,
+ int options=0):docBookmark(bmkname, 0), pattern(pattrn),
+ opts(options) { from=0; to=100; };
+ virtual ~ docMatchBookmark() { };
+
+ virtual int findMatches(QString, bmkList &fBookmarks);
+ QString pattern;
+ int opts;
+ int from, to;
+};
+
+class docRegExpBookmark:public docMatchBookmark {
+ public:
+ docRegExpBookmark():docMatchBookmark() { capSubexpression=-1;};
+ docRegExpBookmark(QString regexp, int cap=0,
+ int options=0):docMatchBookmark(regexp, options) {capSubexpression=cap; };
+ docRegExpBookmark(QString pattrn, QString bmkname,
+ int options=0):docMatchBookmark(pattrn, bmkname, options) { capSubexpression=-1; };
+ virtual ~ docRegExpBookmark() { };
+
+ virtual int findMatches(QString, bmkList &fBookmarks);
+ int capSubexpression;
+};
+
+
+/*************************************************************************************************************
+ * The converter class that does the real work for us.
+ *************************************************************************************************************/
+
+class DOCConverter:public QObject {
+Q_OBJECT
+private:
+ PilotDatabase * docdb;
+ QString txtfilename;
+ QString bmkfilename;
+ bool compress;
+
+ bmkList fBookmarks;
+public:
+ enum eSortBookmarksEnum
+ {
+ eSortNone,
+ eSortPos,
+ eSortName
+ } eSortBookmarks;
+
+public:
+ DOCConverter(QObject *parent=0L, const char *name=0L);
+ virtual ~ DOCConverter();
+
+ QString readText();
+ void setTXTpath(QString path, QString file);
+ void setTXTpath(QString filename);
+ void setPDB(PilotDatabase * dbi);
+ QString txtFilename() const {return txtfilename;}
+ QString bmkFilename() const {return bmkfilename;}
+ void setBmkFilename(QString bmkf) { bmkfilename=bmkf;}
+
+ bool getCompress() const { return compress; };
+ void setCompress(bool newcomp) {compress=newcomp;};
+
+ bool convertTXTtoPDB();
+ bool convertPDBtoTXT();
+
+ int setBookmarks(bmkList bookmarks) {
+ fBookmarks = bookmarks;
+ return fBookmarks.count();
+ };
+ int clearBookmarks() {
+ fBookmarks.clear();
+ return fBookmarks.count();
+ };
+ int addBookmark(docBookmark*bookmark) {
+ fBookmarks.append(bookmark);
+ return fBookmarks.count();
+ };
+
+ int findBmkEndtags(QString &, bmkList&);
+ int findBmkInline(QString &, bmkList&);
+ int findBmkFile(QString &, bmkList&);
+
+
+ void setSort(enum eSortBookmarksEnum sort) {eSortBookmarks=sort;}
+ enum eSortBookmarksEnum getSort() {return eSortBookmarks;}
+
+ enum eBmkTypesEnum {
+ eBmkNone = 0,
+ eBmkFile = 1,
+ eBmkInline = 2,
+ eBmkEndtags = 4,
+ eBmkDefaultBmkFile = 8
+ } fBmkTypes;
+ void setBookmarkTypes(int types) {
+ fBmkTypes = (eBmkTypesEnum) types;
+ };
+
+protected:
+ int findBookmarks();
+
+private:
+ void readConfig();
+signals:
+ void logMessage(const QString &);
+ void logError(const QString &);
+};
+
+#endif
diff --git a/kpilot/conduits/docconduit/Icons/CMakeLists.txt b/kpilot/conduits/docconduit/Icons/CMakeLists.txt
new file mode 100644
index 000000000..3d1034d44
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/CMakeLists.txt
@@ -0,0 +1,3 @@
+
+kde3_install_icons_custom( hicolor )
+
diff --git a/kpilot/conduits/docconduit/Icons/Makefile.am b/kpilot/conduits/docconduit/Icons/Makefile.am
new file mode 100644
index 000000000..f371f4aed
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/Makefile.am
@@ -0,0 +1,7 @@
+METASOURCES = AUTO
+
+kpalmdocicondir = $(kde_datadir)/kpilot/icons
+kpalmdocicon_ICON = kpalmdoc
+
+KDE_ICON = kpalmdoc
+
diff --git a/kpilot/conduits/docconduit/Icons/cr16-app-kpalmdoc.png b/kpilot/conduits/docconduit/Icons/cr16-app-kpalmdoc.png
new file mode 100644
index 000000000..0f5fb75d5
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/cr16-app-kpalmdoc.png
Binary files differ
diff --git a/kpilot/conduits/docconduit/Icons/cr22-app-kpalmdoc.png b/kpilot/conduits/docconduit/Icons/cr22-app-kpalmdoc.png
new file mode 100644
index 000000000..d93aa4bae
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/cr22-app-kpalmdoc.png
Binary files differ
diff --git a/kpilot/conduits/docconduit/Icons/cr32-app-kpalmdoc.png b/kpilot/conduits/docconduit/Icons/cr32-app-kpalmdoc.png
new file mode 100644
index 000000000..09a7020b5
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/cr32-app-kpalmdoc.png
Binary files differ
diff --git a/kpilot/conduits/docconduit/Icons/cr48-app-kpalmdoc.png b/kpilot/conduits/docconduit/Icons/cr48-app-kpalmdoc.png
new file mode 100644
index 000000000..41cb3b9b1
--- /dev/null
+++ b/kpilot/conduits/docconduit/Icons/cr48-app-kpalmdoc.png
Binary files differ
diff --git a/kpilot/conduits/docconduit/Makefile.am b/kpilot/conduits/docconduit/Makefile.am
new file mode 100644
index 000000000..77df2b61b
--- /dev/null
+++ b/kpilot/conduits/docconduit/Makefile.am
@@ -0,0 +1,38 @@
+### Makefile for KPilot's doc conduit
+###
+### The doc conduit is Copyright (C) 2002 by Reinhold Kainhofer
+### the files makedoc9.{h,cpp} are also Copyright (C) 2000 by Pat Beirne
+
+SUBDIRS = Icons
+
+INCLUDES= $(PISOCK_INCLUDE) -I$(top_srcdir)/kpilot/lib $(all_includes)
+METASOURCES = AUTO
+
+
+servicedir = $(kde_servicesdir)
+service_DATA = doc_conduit.desktop
+
+noinst_LTLIBRARIES = libpalmdoc_shared.la
+kde_module_LTLIBRARIES = conduit_doc.la
+bin_PROGRAMS = kpalmdoc
+
+libpalmdoc_shared_la_SOURCES = makedoc9.cc pilotDOCHead.cc pilotDOCEntry.cc pilotDOCBookmark.cc DOC-converter.cc
+
+conduit_doc_la_SOURCES = docconduitSettings.kcfgc doc-factory.cc doc-setup.cc doc-conduit.cc doc-setupdialog.ui doc-conflictdialog.cc
+conduit_doc_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries)
+conduit_doc_la_LIBADD = ../../lib/libkpilot.la libpalmdoc_shared.la \
+ $(LIB_KDEUI) $(LIB_KFILE)
+
+##libpalmdoc_shared.la
+
+kpalmdoc_SOURCES = kpalmdocSettings.kcfgc kpalmdoc_dlgbase.ui kpalmdoc_dlg.cc kpalmdoc.cpp
+kpalmdoc_LDFLAGS = $(PISOCK_LDFLAGS) $(all_libraries) $(KDE_RPATH)
+kpalmdoc_LDADD = $(LIB_KFILE) $(PISOCK_LIB) ../../lib/libkpilot.la libpalmdoc_shared.la
+
+xdg_apps_DATA = kpalmdoc.desktop
+servicetypedir = $(kde_servicetypesdir)
+kde_kcfg_DATA = docconduit.kcfg kpalmdoc.kcfg
+
+update_DATA = kpalmdoc.upd
+updatedir = $(kde_datadir)/kconf_update
+
diff --git a/kpilot/conduits/docconduit/bmkSpecification.txt b/kpilot/conduits/docconduit/bmkSpecification.txt
new file mode 100644
index 000000000..f8a68d961
--- /dev/null
+++ b/kpilot/conduits/docconduit/bmkSpecification.txt
@@ -0,0 +1,199 @@
+KPilot PalmDoc Conduit bookmark Specification
+=============================================
+
+(c) 2003 Reinhold Kainhofer, [email protected]
+
+This document is licensed under the FDL (Free Documentation License)
+as published by the FSF. Any version of the FDL can be applied
+at your convenience.
+
+
+
+
+The PalmDoc conduit has three ways to indicate bookmarks for a text:
+ -) Inline tags of the form <* bookmarkname *>
+ -) Endtags of the form <bookmarkname> at the end of the document
+ -) Regular expressions in a separate textname.bmk file
+ (textname.bmk ist the filename of the text with the .txt replaced by .bmk)
+
+
+In the design of the .bmk file, I tried to stay close to the
+syntac of MakeDocJ bookmark files, but it turned out that I
+needed to extend the syntax a little. Also, MakeDocJ uses Java
+RegExps, while the PalmDoc conduit uses the QRegExp, which have
+some slight differences (especially concerning the ^ and $
+patterns as well as backreferences). So if you used MakeDocJ,
+the .bmk file syntax will be quite familiar, but you will still
+have to adapt your bookmark files for Qt regular expressions
+instead of Java regular expressions
+
+
+
+1) INLINE TAGS
+
+Whenever a tag of the form <* someText *> appears in the text,
+this sequence is removed from the text, and a bookmark is set
+there with the bookmark name "someText" (the part between the
+<* and the *>).
+
+
+2) ENDTAGS
+
+If the text ends with tags of the form <someText>, the string
+in braces is used as bookmark name, and wherever it appears in
+the text, a bookmark is set.
+After the > any number of whitespace is allowed, but no other
+characters like letters, numbers, or punctuation. Also, inside
+the braces no line break must occur. The conduit searches the
+text from the end and if it finds a line break inside a <...>
+sequence, the tag and everything before it is assumed to belong
+to the text and doesn't form a bookmark tag.
+Between endtags any number of whitespace (spaces, tabs, line
+feeds etc.) is allowed.
+
+As an example, assume you have a text ending in:
+... the bad guy was punished, and they lived happily
+ever after!
+<Tag with
+line feed>
+ <bad guy> <princess>
+<married>
+
+The conduit starts at the end, ignores all whitespace between
+the tags, so it finds the tags "married", "princess", and "bad guy".
+The "Tag with line feed" has a line feed, so it is assumed to belong
+to the text.
+Assume now you have a text ending in:
+... the bad guy was punished, and they lived happily
+ever after!
+<bad guy> The End <princess>
+<married>
+
+Here, only "married" and "princess" are found as bookmarks. Because
+of the letters before the "princess" tags, the search for the
+bookmarks ends at the letter "d" of "The End" (the conduit starts
+from the end and moves backward until it finds some text which
+cannot be seen as a endtag.
+
+
+
+
+3) REGULAR EXPRESSIONS IN A SEPARATE FILE
+
+This is by far the most complex way to specify bookmarks, but
+it is also the mose powerful.
+If you have a text with filename "My fairy tale.txt", the
+bookmarks will be specified in a file called "My fairy tale.bmk"
+(just the text filename with the .txt replaced by .bmk). This
+file contains the bookmark definitions, one in each line. Lines
+starting with a # are seen as comments, and empty lines are also
+ignored.
+
+
+In the .bmk file, each bookmark line has one of the following syntaces
+(I will explain all fields later on). Fields in [..] are optional:
+
+bmkName
+bmkPosition, bmkName
++, bmkPatternRegExp[, bmkNameAsString[, firstIncludedBmk[, lastIncludedBmk]]]
++, bmkPatternRegExp[, bmkNameIndexOfSubexpression[, firstIncludedBmk[, lastIncludedBmk]]]
+-, bmkPatternRegExp[, bmkNameAsString]
+-, bmkPatternRegExp[, bmkNameIndexOfSubexpression]
+
+ If the first field is a string, it is used as the bookmark name
+and pattern to search for.
+ If the first field is a number, it means the position of the
+bookmark, and the second field is the name of the bookmark.
+ If the first field is either + or -, the second field gives
+a regular expression that is used to find the position of the
+bookmark. If the first field is a -, the search is done only
+once and only the first match will be added as bookmark. If
+the first field is a +, the search is done until the regular
+expression can no longer be found (the fourth and fifth fields
+can be used to include only a certain range of hits). If there
+is a third field, and it is a string, it gives the name of the
+bookmark as a regular expression (i.e. \1 are replaced by the
+first subexpression of the search, where subexpressions are
+specified by round brackets in the regexp of the second field).
+If there is a third field, and it is a number, it gives the index
+of the subexpression of bmkPatternRegExp that is used as the
+bookmark name.
+If there is no third field, the whole matched text will be used
+as bookmark name.
+The optional fourth and fifth fields can be used to set bookmarks
+only after the first few ocurrences of the regexp in the text, and
+to stop the search after the expression has been found a certain
+number of times.
+
+
+
+If the PDB->PC sync is set up to store the bookmarks in a bookmark file,
+it will create a file "My fairy tale.bm" (no "k") with entries of the form
+position,bmkName
+The .bmk file will be used if it exists, but if no .bmk file exists, the .bm file
+will be used. This way you can override the bookmark settings, while
+at the same time the PDB->TXT sync does not destroy your possibly
+existing .bmk file.
+
+
+
+Examples:
+
+1) Imagine you have a line like:
+frog princess
+In this case, the text is searched for "frog princess", and a
+bookmark is set whenever "frog princess" occurs in the text.
+The name of each of these bookmarks will be "frog princess".
+
+2) A bookmark line:
+55, Bookmark at offset 55
+Here, a bookmark will be set at offset 55 (55th character of
+the text), and it will have the name "Bookmark at offs" (truncated
+to 16 characters)
+
+3) A bookmark line
+-,Chapter \d+
+causes a bookmark to be set at the first ocurrence of "Chapter XXX",
+where XXX denotes one or more digits. The bookmark name will be
+"Chapter XXX" (XXX replaced by the actual digits).
+
+4) A bookmark line
++,Chapter \d+
+causes bookmarks to be set wherever "Chapter XXX" (XXX being one
+or more digits) appears in the text. The bookmark name will again
+be "Chapter XXX", but the search does not stop after the first hit.
+
+5) A bookmark line
++,\n\s*(Chapter \d+)\D+, 1
+causes a bookmark to be set whenever a new line starts with
+"Chapter XXX" (whitespace is allowed before the "Chapter"), and
+uses the first subexpression in (..) as the bookmark name. If you
+have a passage
+ Chapter 15: here it starts
+The regular expression will match, so a bookmark will be set there
+and the subexpression "Chapter 15" (which matches the (Chapter \d+) )
+will be used as bookmark text.
+
+6) A bookmark line
++,\n\s*Part (\d+),\1\. part
+sets a bookmark whenever a line starts with "Part XXX". The XXX
+will be stored as the first matched subexpression. The third field
+"\1\. part" is the regular expression for the bookmark name, where
+\1 is replaced by the first matched subexpression of the search (XXX
+in this case). So if a line starts with " Part 17: ", the bookmark
+name will be "17. part".
+
+7) A bookmark line
++,Table (\d+): ,\1\. Tabelle,5,25
+will match whenever "Table XXX: " appears in the text, and the bookmark
+name will be "XXX. Tabelle". However, the fourth field means that the
+first four hits are ignored (the 5th hit is the first hit to be included
+as a bookmark), and the fifth field means that all further hits after the
+25th will be ignored, too.
+
+8) In law texts, I use a regular expression
++,\n *(�\.? *\d+[a-z]?\.?) +, 1
+to search for all paragraphs starting like "�. 15. " or " �23 ", and set
+a bookmark there using only the part from the � to the last digit or the
+full stop after the last digit (the pattern between the (), in our two
+cases the bookmark names will be "�. 15." and "�23" ).
diff --git a/kpilot/conduits/docconduit/doc-conduit.cc b/kpilot/conduits/docconduit/doc-conduit.cc
new file mode 100644
index 000000000..eee36080c
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-conduit.cc
@@ -0,0 +1,1018 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** The doc conduit synchronizes text files on the PC with DOC databases on the Palm
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected].
+*/
+
+
+// naming of the bookmark file:
+// PDB->TXT: convert bookmarks to a .bm file
+// TXT->PDB: If a .bmk file exists, use it, otherwise use the .bm file (from the PDB->TXT conversion)
+// This way, the bookmark file is not overwritten, a manual bookmark file overrides, but the bookmarks from the handheld are still available
+
+
+#include "options.h"
+#include "doc-conduit.moc"
+
+#include <qtimer.h>
+#include <qdir.h>
+
+#include <kconfig.h>
+#include <kmdcodec.h>
+
+#include <pilotLocalDatabase.h>
+#include <pilotSerialDatabase.h>
+
+#include "doc-factory.h"
+#include "doc-conflictdialog.h"
+#include "DOC-converter.h"
+#include "pilotDOCHead.h"
+#include "docconduitSettings.h"
+
+
+// Something to allow us to check what revision
+// the modules are that make up a binary distribution.
+extern "C"
+{
+unsigned long version_conduit_doc = Pilot::PLUGIN_API;
+}
+
+QString dirToString(eSyncDirectionEnum dir) {
+ switch(dir) {
+// case eSyncAll: return "eSyncAll";
+ case eSyncPDAToPC: return CSL1("eSyncPDAToPC");
+ case eSyncPCToPDA: return CSL1("eSyncPCToPDA");
+ case eSyncNone: return CSL1("eSyncNone");
+ case eSyncConflict: return CSL1("eSyncConflict");
+ case eSyncDelete: return CSL1("eSyncDelete");
+ default: return CSL1("ERROR");
+ }
+}
+
+
+/*********************************************************************
+ C O N S T R U C T O R
+ *********************************************************************/
+
+
+DOCConduit::DOCConduit(KPilotLink * o,
+ const char *n, const QStringList & a):ConduitAction(o, n, a)
+{
+ FUNCTIONSETUP;
+ fConduitName=i18n("DOC");
+}
+
+
+
+DOCConduit::~DOCConduit()
+{
+ FUNCTIONSETUP;
+}
+
+
+bool DOCConduit::isCorrectDBTypeCreator(DBInfo dbinfo) {
+ return dbinfo.type == dbtype() && dbinfo.creator == dbcreator();
+}
+const unsigned long DOCConduit::dbtype() {
+ return get_long(DOCConduitFactory::dbDOCtype);
+}
+const unsigned long DOCConduit::dbcreator() {
+ return get_long(DOCConduitFactory::dbDOCcreator);
+}
+
+
+
+/*********************************************************************
+ L O A D I N G T H E D A T A
+ *********************************************************************/
+
+
+
+void DOCConduit::readConfig()
+{
+ FUNCTIONSETUP;
+ DOCConduitSettings::self()->readConfig();
+
+ eConflictResolution = (enum eSyncDirectionEnum) (DOCConduitSettings::conflictResolution() );
+ fTXTBookmarks = DOCConverter::eBmkNone;
+ if ( DOCConduitSettings::convertBookmarks() )
+ {
+ if ( DOCConduitSettings::bmkFileBookmarks() )
+ fTXTBookmarks |= DOCConverter::eBmkFile;
+ if ( DOCConduitSettings::inlineBookmarks() )
+ fTXTBookmarks |= DOCConverter::eBmkInline;
+ if ( DOCConduitSettings::endtagBookmarks() )
+ fTXTBookmarks |= DOCConverter::eBmkEndtags;
+ }
+
+ eSyncDirection = (enum eSyncDirectionEnum)(DOCConduitSettings::syncDirection() );
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname
+ << ": Settings "
+ << " tXTDirectory=" << DOCConduitSettings::tXTDirectory()
+ << " pDBDirectory=" << DOCConduitSettings::pDBDirectory()
+ << " keepPDBLocally=" << DOCConduitSettings::keepPDBsLocally()
+ << " eConflictResolution=" << eConflictResolution
+ << " tXTBookmarks=" << fTXTBookmarks
+ << " pDBBookmarks=" << DOCConduitSettings::bookmarksToPC()
+ << " compress=" << DOCConduitSettings::compress()
+ << " eSyncDirection=" << eSyncDirection << endl;
+#endif
+}
+
+
+
+bool DOCConduit::pcTextChanged(QString txtfn)
+{
+ FUNCTIONSETUP;
+ // How do I find out if a text file has changed shince we last synced it??
+ // Use KMD5 for now. If I realize it is too slow, then I have to go back to comparing modification times
+ // if there is no config setting yet, assume the file has been changed. the md5 sum will be written to the config file after the sync.
+ QString oldDigest=DOCConduitSettings::self()->config()->readEntry(txtfn);
+ if (oldDigest.length()<=0)
+ {
+ return true;
+ }
+#ifdef DEBUG
+ DEBUGKPILOT<<"Old digest is "<<oldDigest<<endl;
+#endif
+
+ KMD5 docmd5;
+ QFile txtfile(txtfn);
+ if (txtfile.open(IO_ReadOnly)){
+ docmd5.update(txtfile);
+ QString thisDigest(docmd5.hexDigest() /* .data() */);
+#ifdef DEBUG
+ DEBUGKPILOT<<"New digest is "<<thisDigest<<endl;
+#endif
+ return (thisDigest.length()<=0) || (thisDigest!=oldDigest);
+ } else {
+ // File does not exist. This should actually never happen. Anyways, just return true to indicate it has changed.
+ // doSync should detect this and delete the doc from the handheld.
+ return true;
+ }
+ return false;
+}
+
+
+
+bool DOCConduit::hhTextChanged(PilotDatabase*docdb)
+{
+ FUNCTIONSETUP;
+ if (!docdb) return false;
+
+ PilotRecord *firstRec = docdb->readRecordByIndex(0);
+ PilotDOCHead docHeader(firstRec);
+ KPILOT_DELETE(firstRec);
+
+ int storyRecs = docHeader.numRecords;
+
+ // determine the index of the next modified record (does it lie
+ // beyond the actual text records?)
+ int modRecInd=-1;
+ PilotRecord*modRec=docdb->readNextModifiedRec(&modRecInd);
+#ifdef DEBUG
+ DEBUGKPILOT<<"Index of first changed record: "<<modRecInd<<endl;
+#endif
+
+ KPILOT_DELETE(modRec);
+ // if the header record was changed, find out which is the first changed
+ // real document record:
+ if (modRecInd==0) {
+ modRec=docdb->readNextModifiedRec(&modRecInd);
+#ifdef DEBUG
+ DEBUGKPILOT<<"Reread Index of first changed records: "<<modRecInd<<endl;
+#endif
+ KPILOT_DELETE(modRec);
+ }
+
+ // The record index starts with 0, so only a negative number means
+ // no modified record was found
+ if (modRecInd >= 0) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Handheld side has changed, condition="<<
+ ((!DOCConduitSettings::ignoreBmkChanges()) || (modRecInd <= storyRecs))<<endl;
+#endif
+ if ((!DOCConduitSettings::ignoreBmkChanges()) || (modRecInd <= storyRecs))
+ return true;
+ } else {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Handheld side has NOT changed!"<<endl;
+#endif
+ return false;
+ }
+ return false;
+}
+
+
+
+/*********************************************************************
+ * Helper functions
+ ********************************************************************/
+
+QString DOCConduit::constructPDBFileName(QString name) {
+ FUNCTIONSETUP;
+ QString fn;
+ QDir dr(DOCConduitSettings::pDBDirectory());
+ QFileInfo pth(dr, name);
+ if (!name.isEmpty()) fn=pth.absFilePath()+CSL1(".pdb");
+ return fn;
+}
+QString DOCConduit::constructTXTFileName(QString name) {
+ FUNCTIONSETUP;
+ QString fn;
+ QDir dr( DOCConduitSettings::tXTDirectory() );
+ QFileInfo pth(dr, name);
+ if (!name.isEmpty()) fn=pth.absFilePath()+CSL1(".txt");
+ return fn;
+}
+
+
+
+
+
+/*********************************************************************
+ S Y N C S T R U C T U R E
+ *********************************************************************/
+
+
+
+
+
+/* virtual */ bool DOCConduit::exec()
+{
+ FUNCTIONSETUP;
+
+ readConfig();
+ dbnr=0;
+
+ emit logMessage(i18n("Searching for texts and databases to synchronize"));
+
+ QTimer::singleShot(0, this, SLOT(syncNextDB()));
+ return true;
+}
+
+
+
+bool DOCConduit::doSync(docSyncInfo &sinfo)
+{
+ FUNCTIONSETUP;
+ bool res=false;
+
+ if (sinfo.direction==eSyncDelete) {
+ if (!sinfo.txtfilename.isEmpty()) {
+ if (!QFile::remove(sinfo.txtfilename)) {
+ WARNINGKPILOT << "Unable to delete the text file " << sinfo.txtfilename << " on the PC" << endl;
+ }
+ QString bmkfilename = sinfo.txtfilename;
+ if (bmkfilename.endsWith(CSL1(".txt"))){
+ bmkfilename.remove(bmkfilename.length()-4, 4);
+ }
+ bmkfilename+=CSL1(PDBBMK_SUFFIX);
+ if (!QFile::remove(bmkfilename)) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Could not remove bookmarks file "<<bmkfilename<<" for database "<<sinfo.handheldDB<<endl;
+#endif
+ }
+ }
+ if (!sinfo.pdbfilename.isEmpty() && DOCConduitSettings::keepPDBsLocally() ) {
+ PilotLocalDatabase*database=new PilotLocalDatabase(DOCConduitSettings::pDBDirectory(),
+ QString::fromLatin1(sinfo.dbinfo.name), false);
+ if (database) {
+ if ( database->deleteDatabase() !=0 ) {
+ WARNINGKPILOT << "Unable to delete database " << sinfo.dbinfo.name << " on the PC" << endl;
+ }
+ KPILOT_DELETE(database);
+ }
+ }
+ if (!DOCConduitSettings::localSync()) {
+ PilotDatabase *database=deviceLink()->database( sinfo.dbinfo.name );
+ if ( database->deleteDatabase() !=0 ) {
+ WARNINGKPILOT << "Unable to delete database " << sinfo.dbinfo.name << " from the handheld" << endl;
+ }
+ KPILOT_DELETE(database);
+ }
+ return true;
+ }
+ // preSyncAction should initialize the custom databases/files for the
+ // specific action chosen for this db and return a pointer to a docDBInfo
+ // instance which points either to a local database or a database on the handheld.
+ PilotDatabase *database = preSyncAction(sinfo);
+
+ if (database && ( !database->isOpen() ) ) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Database "<<sinfo.dbinfo.name<<" does not yet exist. Creating it:"<<endl;
+#endif
+ if (!database->createDatabase(dbcreator(), dbtype()) ) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Failed"<<endl;
+ emit logMessage(i18n("Database created."));
+#endif
+ }
+ }
+
+ if (database && database->isOpen()) {
+ DOCConverter docconverter;
+ connect(&docconverter, SIGNAL(logError(const QString &)), SIGNAL(logError(const QString &)));
+ connect(&docconverter, SIGNAL(logMessage(const QString &)), SIGNAL(logMessage(const QString &)));
+
+ docconverter.setTXTpath( DOCConduitSettings::tXTDirectory(), sinfo.txtfilename );
+ docconverter.setPDB(database);
+ docconverter.setCompress(DOCConduitSettings::compress());
+
+ switch (sinfo.direction) {
+ case eSyncPDAToPC:
+ docconverter.setBookmarkTypes(DOCConduitSettings::bookmarksToPC());
+ res = docconverter.convertPDBtoTXT();
+ break;
+ case eSyncPCToPDA:
+ docconverter.setBookmarkTypes(fTXTBookmarks);
+ res = docconverter.convertTXTtoPDB();
+ break;
+ default:
+ break;
+ }
+
+ // Now calculate the md5 checksum of the PC text and write it to the config file
+ if (res)
+ {
+ KMD5 docmd5;
+ QFile txtfile(docconverter.txtFilename());
+ if (txtfile.open(IO_ReadOnly)) {
+ docmd5.update(txtfile);
+ QString thisDigest(docmd5.hexDigest() /* .data() */);
+ DOCConduitSettings::self()->config()->writeEntry(docconverter.txtFilename(), thisDigest);
+ DOCConduitSettings::self()->config()->sync();
+#ifdef DEBUG
+ DEBUGKPILOT<<"MD5 Checksum of the text "<<sinfo.txtfilename<<" is "<<thisDigest<<endl;
+#endif
+ } else {
+#ifdef DEBUG
+ DEBUGKPILOT<<"couldn't open file "<<docconverter.txtFilename()<<" for reading!!!"<<endl;
+#endif
+ }
+ }
+
+ if (!postSyncAction(database, sinfo, res))
+ emit logError(i18n("Unable to install the locally created PalmDOC %1 to the handheld.")
+ .arg(QString::fromLatin1(sinfo.dbinfo.name)));
+ if (!res)
+ emit logError(i18n("Conversion of PalmDOC \"%1\" failed.")
+ .arg(QString::fromLatin1(sinfo.dbinfo.name)));
+// disconnect(&docconverter, SIGNAL(logError(const QString &)), SIGNAL(logError(const QString &)));
+// disconnect(&docconverter, SIGNAL(logMessage(const QString &)), SIGNAL(logMessage(const QString &)));
+// KPILOT_DELETE(database);
+ }
+ else
+ {
+ emit logError(i18n("Unable to open or create the database %1.")
+ .arg(QString::fromLatin1(sinfo.dbinfo.name)));
+ }
+ return res;
+}
+
+
+/** syncNextDB walks through all PalmDoc databases on the handheld and decides if they are supposed to be synced to the PC.
+ * syncNextDB and syncNextTXT fist build the list of all PalmDoc texts, and then the method syncDatabases does the actual sync. */
+void DOCConduit::syncNextDB() {
+ FUNCTIONSETUP;
+ DBInfo dbinfo;
+
+ if (eSyncDirection==eSyncPCToPDA || fHandle->findDatabase(NULL, &dbinfo, dbnr, dbtype(), dbcreator() /*, cardno */ ) < 0)
+ {
+ // no more databases available, so check for PC->Palm sync
+ QTimer::singleShot(0, this, SLOT(syncNextTXT()));
+ return;
+ }
+ dbnr=dbinfo.index+1;
+#ifdef DEBUG
+ DEBUGKPILOT<<"Next Palm database to sync: "<<dbinfo.name<<", Index="<<dbinfo.index<<endl;
+#endif
+
+ // if creator and/or type don't match, go to next db
+ if (!isCorrectDBTypeCreator(dbinfo) ||
+ fDBNames.contains(QString::fromLatin1(dbinfo.name)))
+ {
+ QTimer::singleShot(0, this, SLOT(syncNextDB()));
+ return;
+ }
+
+ QString txtfilename=constructTXTFileName(QString::fromLatin1(dbinfo.name));
+ QString pdbfilename=constructPDBFileName(QString::fromLatin1(dbinfo.name));
+
+ docSyncInfo syncInfo(QString::fromLatin1(dbinfo.name),
+ txtfilename, pdbfilename, eSyncNone);
+ syncInfo.dbinfo=dbinfo;
+ needsSync(syncInfo);
+ fSyncInfoList.append(syncInfo);
+ fDBNames.append(QString::fromLatin1(dbinfo.name));
+
+ QTimer::singleShot(0, this, SLOT(syncNextDB()));
+ return;
+}
+
+
+
+void DOCConduit::syncNextTXT()
+{
+ FUNCTIONSETUP;
+
+ if (eSyncDirection==eSyncPDAToPC )
+ {
+ // We don't sync from PC to PDB, so start the conflict resolution and then the actual sync process
+ docnames.clear();
+ QTimer::singleShot(0, this, SLOT(checkPDBFiles()));
+ return;
+ }
+
+ // if docnames isn't initialized, get a list of all *.txt files in DOCConduitSettings::tXTDirectory()
+ if (docnames.isEmpty()/* || dociterator==docnames.end() */) {
+ docnames=QDir( DOCConduitSettings::tXTDirectory(), CSL1("*.txt")).entryList() ;
+ dociterator=docnames.begin();
+ }
+ if (dociterator==docnames.end()) {
+ // no more databases available, so start the conflict resolution and then the actual sync proces
+ docnames.clear();
+ QTimer::singleShot(0, this, SLOT(checkPDBFiles()));
+ return;
+ }
+
+ QString fn=(*dociterator);
+
+ QDir dr( DOCConduitSettings::tXTDirectory() );
+ QFileInfo fl(dr, fn );
+ QString txtfilename=fl.absFilePath();
+ QString pdbfilename;
+ ++dociterator;
+
+ DBInfo dbinfo;
+ // Include all "extensions" except the last. This allows full stops inside the database name (e.g. abbreviations)
+ // first fill everything with 0, so we won't have a buffer overflow.
+ memset(&dbinfo.name[0], 0, 33);
+ strncpy(&dbinfo.name[0], fl.baseName(TRUE).latin1(), 30);
+
+ bool alreadySynced=fDBNames.contains(fl.baseName(TRUE));
+ if (!alreadySynced) {
+ docSyncInfo syncInfo(QString::fromLatin1(dbinfo.name),
+ txtfilename, pdbfilename, eSyncNone);
+ syncInfo.dbinfo=dbinfo;
+ needsSync(syncInfo);
+ fSyncInfoList.append(syncInfo);
+ fDBNames.append(QString::fromLatin1(dbinfo.name));
+ } else {
+#ifdef DEBUG
+ DEBUGKPILOT<<txtfilename<<" has already been synced, skipping it."<<endl;
+#endif
+ }
+
+ QTimer::singleShot(0, this, SLOT(syncNextTXT()));
+ return;
+}
+
+
+
+/** This slot will only be used if DOCConduitSettings::keepPDBsLocally() to check if new doc databases have been copied to the pdb directory.
+ * If so, install it to the handheld and sync it to the PC */
+void DOCConduit::checkPDBFiles() {
+ FUNCTIONSETUP;
+
+ if ( DOCConduitSettings::localSync() || !DOCConduitSettings::keepPDBsLocally() || eSyncDirection==eSyncPCToPDA )
+ {
+ // no more databases available, so check for PC->Palm sync
+ QTimer::singleShot(0, this, SLOT(checkDeletedDocs()));
+ return;
+ }
+
+ // Walk through all files in the pdb directory and check if it has already been synced.
+ // if docnames isn't initialized, get a list of all *.pdb files in DOCConduitSettings::pDBDirectory()
+ if (docnames.isEmpty()/* || dociterator==docnames.end() */) {
+ docnames=QDir(DOCConduitSettings::pDBDirectory(), CSL1("*.pdb")).entryList() ;
+ dociterator=docnames.begin();
+ }
+ if (dociterator==docnames.end()) {
+ // no more databases available, so start the conflict resolution and then the actual sync proces
+ docnames.clear();
+ QTimer::singleShot(0, this, SLOT(checkDeletedDocs()));
+ return;
+ }
+
+ QString fn=(*dociterator);
+
+ QDir dr(DOCConduitSettings::pDBDirectory());
+ QFileInfo fl(dr, fn );
+ QString pdbfilename=fl.absFilePath();
+ ++dociterator;
+
+ // Get the doc title and check if it has already been synced (in the synced docs list of in fDBNames to be synced)
+ // If the doc title doesn't appear in either list, install it to the Handheld, and add it to the list of dbs to be synced.
+ QString dbname=fl.baseName(TRUE).left(30);
+ if (!fDBNames.contains(dbname) && !fDBListSynced.contains(dbname)) {
+ if (fHandle->installFiles(pdbfilename, false)) {
+ DBInfo dbinfo;
+ // Include all "extensions" except the last. This allows full stops inside the database name (e.g. abbreviations)
+ // first fill everything with 0, so we won't have a buffer overflow.
+ memset(&dbinfo.name[0], 0, 33);
+ strncpy(&dbinfo.name[0], dbname.latin1(), 30);
+
+ docSyncInfo syncInfo(dbname, constructTXTFileName(dbname), pdbfilename, eSyncNone);
+ syncInfo.dbinfo=dbinfo;
+ needsSync(syncInfo);
+ fSyncInfoList.append(syncInfo);
+ fDBNames.append(dbname);
+ } else {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Could not install database "<<dbname<<" ("<<pdbfilename<<") to the handheld"<<endl;
+#endif
+ }
+ }
+
+ QTimer::singleShot(0, this, SLOT(checkPDBFiles()));
+}
+
+
+
+void DOCConduit::checkDeletedDocs()
+{
+ FUNCTIONSETUP;
+
+ for (QStringList::Iterator it=fDBListSynced.begin(); it!=fDBListSynced.end(); ++it ) {
+ if (!fDBNames.contains(*it)) {
+ // We need to delete this doc:
+ QString dbname(*it);
+ QString txtfilename=constructTXTFileName(dbname);
+ QString pdbfilename=constructPDBFileName(dbname);
+ docSyncInfo syncInfo(dbname, txtfilename, pdbfilename, eSyncDelete);
+
+ DBInfo dbinfo;
+ memset(&dbinfo.name[0], 0, 33);
+ strncpy(&dbinfo.name[0], dbname.latin1(), 30);
+ syncInfo.dbinfo=dbinfo;
+
+ fSyncInfoList.append(syncInfo);
+ }
+ }
+ QTimer::singleShot(0, this, SLOT(resolve()));
+ return;
+}
+
+
+
+void DOCConduit::resolve() {
+ FUNCTIONSETUP;
+
+ for (fSyncInfoListIterator=fSyncInfoList.begin(); fSyncInfoListIterator!=fSyncInfoList.end(); ++fSyncInfoListIterator) {
+ // Walk through each database and apply the conflictResolution option.
+ // the remaining conflicts will be resolved in the resolution dialog
+ if ((*fSyncInfoListIterator).direction==eSyncConflict){
+#ifdef DEBUG
+ DEBUGKPILOT<<"We have a conflict for "<<(*fSyncInfoListIterator).handheldDB<<", default="<<eConflictResolution<<endl;
+#endif
+ switch (eConflictResolution)
+ {
+ case eSyncPDAToPC:
+#ifdef DEBUG
+ DEBUGKPILOT<<"PDA overrides for database "<<(*fSyncInfoListIterator).handheldDB<<endl;
+#endif
+ (*fSyncInfoListIterator).direction = eSyncPDAToPC;
+ break;
+ case eSyncPCToPDA:
+#ifdef DEBUG
+ DEBUGKPILOT<<"PC overrides for database "<<(*fSyncInfoListIterator).handheldDB<<endl;
+#endif
+ (*fSyncInfoListIterator).direction = eSyncPCToPDA;
+ break;
+ case eSyncNone:
+#ifdef DEBUG
+ DEBUGKPILOT<<"No sync for database "<<(*fSyncInfoListIterator).handheldDB<<endl;
+#endif
+ (*fSyncInfoListIterator).direction = eSyncNone;
+ break;
+ case eSyncDelete:
+ case eSyncConflict:
+ default:
+#ifdef DEBUG
+ DEBUGKPILOT<<"Conflict remains due to default resolution setting for database "<<(*fSyncInfoListIterator).handheldDB<<endl;
+#endif
+ break;
+ }
+ }
+ }
+
+ // Show the conflict resolution dialog and ask for the action for each database
+ ResolutionDialog*dlg=new ResolutionDialog( 0, i18n("Conflict Resolution"), &fSyncInfoList , fHandle);
+ bool show=DOCConduitSettings::alwaysShowResolutionDialog() || (dlg && dlg->hasConflicts);
+ if (show) {
+ if (!dlg || !dlg->exec() ) {
+ KPILOT_DELETE(dlg)
+ emit logMessage(i18n("Sync aborted by user."));
+ QTimer::singleShot(0, this, SLOT(cleanup()));
+ return;
+ }
+ }
+ KPILOT_DELETE(dlg)
+
+
+ // fDBNames will be filled with the names of the databases that are actually synced (not deleted), so I can write the list to the config file
+ fDBNames.clear();
+ fSyncInfoListIterator=fSyncInfoList.begin();
+ QTimer::singleShot(0,this, SLOT(syncDatabases()));
+ return;
+}
+
+
+
+void DOCConduit::syncDatabases() {
+ FUNCTIONSETUP;
+ if (fSyncInfoListIterator==fSyncInfoList.end()) {
+ // We're done, so clean up
+ QTimer::singleShot(0, this, SLOT(cleanup()));
+ return;
+ }
+
+ docSyncInfo sinfo=(*fSyncInfoListIterator);
+ ++fSyncInfoListIterator;
+
+ switch (sinfo.direction) {
+ case eSyncConflict:
+#ifdef DEBUG
+ DEBUGKPILOT<<"Entry "<<sinfo.handheldDB<<"( txtfilename: "<<sinfo.txtfilename<<
+ ", pdbfilename: "<<sinfo.pdbfilename<<") had sync direction eSyncConflict!!!"<<endl;
+#endif
+ break;
+ case eSyncDelete:
+ case eSyncPDAToPC:
+ case eSyncPCToPDA:
+ emit logMessage(i18n("Synchronizing text \"%1\"").arg(sinfo.handheldDB));
+ if (!doSync(sinfo)) {
+ // The sync could not be done, so inform the user (the error message should probably issued inside doSync)
+#ifdef DEBUG
+ DEBUGKPILOT<<"There was some error syncing the text \""<<sinfo.handheldDB<<"\" with the file "<<sinfo.txtfilename<<endl;
+#endif
+ }
+ break;
+ case eSyncNone:
+// case eSyncAll:
+ break;
+ }
+ if (sinfo.direction != eSyncDelete) fDBNames.append(sinfo.handheldDB);
+
+ QTimer::singleShot(0,this, SLOT(syncDatabases()));
+ return;
+}
+
+
+PilotDatabase*DOCConduit::openDOCDatabase(const QString &dbname) {
+ if (DOCConduitSettings::localSync())
+ {
+ return new PilotLocalDatabase(DOCConduitSettings::pDBDirectory(), dbname, false);
+ }
+ else
+ {
+ return deviceLink()->database( dbname );
+ }
+}
+
+
+bool DOCConduit::needsSync(docSyncInfo &sinfo)
+{
+ FUNCTIONSETUP;
+ sinfo.direction = eSyncNone;
+
+ PilotDatabase*docdb=openDOCDatabase(QString::fromLatin1(sinfo.dbinfo.name));
+ if (!fDBListSynced.contains(sinfo.handheldDB)) {
+ // the database wasn't included on last sync, so it has to be new.
+#ifdef DEBUG
+ DEBUGKPILOT<<"Database "<<sinfo.dbinfo.name<<" wasn't included in the previous sync!"<<endl;
+#endif
+
+ /* Resolution Table:
+ PC HH | normal PC->HH HH->PC
+ -----------------------------------------
+ N - | P P D
+ - N | H D H
+ N N | C P H
+ */
+
+ if (QFile::exists(sinfo.txtfilename)) sinfo.fPCStatus=eStatNew;
+ else sinfo.fPCStatus=eStatDoesntExist;
+ if (docdb && docdb->isOpen()) sinfo.fPalmStatus=eStatNew;
+ else sinfo.fPalmStatus=eStatDoesntExist;
+ KPILOT_DELETE(docdb);
+
+ switch (eSyncDirection) {
+ case eSyncPDAToPC:
+ if (sinfo.fPalmStatus==eStatDoesntExist)
+ sinfo.direction=eSyncDelete;
+ else sinfo.direction=eSyncPDAToPC;
+ break;
+ case eSyncPCToPDA:
+ if (sinfo.fPCStatus==eStatDoesntExist)
+ sinfo.direction=eSyncDelete;
+ else sinfo.direction=eSyncPCToPDA;
+ break;
+ case eSyncNone: // means actually both directions!
+ if (sinfo.fPCStatus==eStatNew) {
+ if (sinfo.fPalmStatus==eStatNew) sinfo.direction=eSyncConflict;
+ else sinfo.direction=eSyncPCToPDA;
+ } else {
+ if (sinfo.fPalmStatus==eStatNew) sinfo.direction=eSyncPDAToPC;
+ else {
+ sinfo.direction=eSyncNone;
+#ifdef DEBUG
+ DEBUGKPILOT<<"I'm supposed to find a sync direction, but the "<<
+ " text "<<sinfo.dbinfo.name<<" doesn't exist on either "<<
+ " the handheld or the PC"<<endl;
+#endif
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+
+ // Text was included in the last sync
+ if (!QFile::exists(sinfo.txtfilename)) sinfo.fPCStatus=eStatDeleted;
+ else if(pcTextChanged(sinfo.txtfilename)) {
+ sinfo.fPCStatus=eStatChanged;
+#ifdef DEBUG
+ DEBUGKPILOT<<"PC side has changed!"<<endl;
+#endif
+ // TODO: Check for changed bookmarks on the PC side
+#ifdef DEBUG
+ } else {
+ DEBUGKPILOT<<"PC side has NOT changed!"<<endl;
+#endif
+ }
+
+ if (!docdb || !docdb->isOpen()) sinfo.fPalmStatus=eStatDeleted;
+ else if (hhTextChanged(docdb)) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Handheld side has changed!"<<endl;
+#endif
+ sinfo.fPalmStatus=eStatChanged;
+#ifdef DEBUG
+ } else {
+ DEBUGKPILOT<<"Handheld side has NOT changed!"<<endl;
+#endif
+ }
+ KPILOT_DELETE(docdb);
+
+
+ // Now that we know the status of both sides, determine what to do.
+ /* Resolution Table:
+ PC HH | normal PC->HH HH->PC
+ -----------------------------------------
+ - - | - - -
+ C - | P P H
+ - C | H P H
+ C C | C P H
+ D - | D D H
+ - D | D P D
+ D D | D D D
+ -----------------------------------------
+ C D | C P D
+ D C | C D H
+ */
+
+
+ if (sinfo.fPCStatus == eStatNone && sinfo.fPalmStatus==eStatNone) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Nothing has changed, not need for a sync."<<endl;
+#endif
+ sinfo.direction=eSyncNone;
+ return false;
+ }
+
+ // In all other cases, if only one direction (PC->HH or HH->PC)
+ // should be done, check if the DB was deleted or if we are supposed
+ // to sync that direction
+
+ if (eSyncDirection==eSyncPCToPDA) {
+ if (sinfo.fPCStatus==eStatDeleted) sinfo.direction=eSyncDelete;
+ else sinfo.direction=eSyncPCToPDA;
+ return true;
+ }
+ if (eSyncDirection==eSyncPDAToPC) {
+ if (sinfo.fPalmStatus==eStatDeleted) sinfo.direction=eSyncDelete;
+ else sinfo.direction=eSyncPDAToPC;
+ return true;
+ }
+
+
+ // ---------------------------------------------------------------
+ // Finally, do the normal case, where both directions are possible
+ // ---------------------------------------------------------------
+
+
+ // if either is deleted, and the other is not changed, delete
+ if ( ((sinfo.fPCStatus==eStatDeleted) && (sinfo.fPalmStatus!=eStatChanged)) ||
+ ((sinfo.fPalmStatus==eStatDeleted) && (sinfo.fPCStatus!=eStatChanged)) )
+ {
+#ifdef DEBUG
+ DEBUGKPILOT<<"DB was deleted on one side and not changed on "
+ "the other -> Delete it."<<endl;
+#endif
+ sinfo.direction=eSyncDelete;
+ return true;
+ }
+
+ // eStatDeleted (and both not changed) have already been treated, for all
+ // other values in combination with eStatNone, just copy the texts.
+ if (sinfo.fPCStatus==eStatNone) {
+#ifdef DEBUG
+ DEBUGKPILOT<<"PC side has changed!"<<endl;
+#endif
+ sinfo.direction=eSyncPDAToPC;
+ return true;
+ }
+
+ if (sinfo.fPalmStatus==eStatNone) {
+ sinfo.direction=eSyncPCToPDA;
+ return true;
+ }
+
+ // All other cases
+ // (deleted,changed), (changed, deleted), (changed,changed)
+ // create a conflict:
+ sinfo.direction=eSyncConflict;
+ return true;
+}
+
+
+
+PilotDatabase *DOCConduit::preSyncAction(docSyncInfo &sinfo) const
+{
+ FUNCTIONSETUP;
+
+ {
+ // make sure the dir for the local texts really exists!
+ QDir dir( DOCConduitSettings::tXTDirectory() );
+ if (!dir.exists())
+ {
+ dir.mkdir(dir.absPath());
+ }
+ }
+
+ DBInfo dbinfo=sinfo.dbinfo;
+ switch (sinfo.direction)
+ {
+ case eSyncPDAToPC:
+ if (DOCConduitSettings::keepPDBsLocally())
+ {
+ // make sure the dir for the local db really exists!
+ QDir dir(DOCConduitSettings::pDBDirectory());
+
+ if (!dir.exists())
+ {
+ dir.mkdir(dir.absPath());
+ }
+#ifdef DEBUG
+ DEBUGKPILOT<<"Need to fetch database "<<dbinfo.name<<
+ " to the directory "<<dir.absPath()<<endl;
+#endif
+ dbinfo.flags &= ~dlpDBFlagOpen;
+
+ if (!fHandle->retrieveDatabase(sinfo.pdbfilename, &dbinfo) )
+ {
+ WARNINGKPILOT << "Unable to retrieve database " << dbinfo.name <<
+ " from the handheld into " << sinfo.pdbfilename << "." << endl;
+ return 0L;
+ }
+ }
+ break;
+ case eSyncPCToPDA:
+ if (DOCConduitSettings::keepPDBsLocally())
+ {
+ // make sure the dir for the local db really exists!
+ QDir dir(DOCConduitSettings::pDBDirectory());
+ if (!dir.exists())
+ {
+ dir.mkdir(dir.absPath());
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ if (DOCConduitSettings::keepPDBsLocally())
+ {
+ return new PilotLocalDatabase(DOCConduitSettings::pDBDirectory(),
+ QString::fromLatin1(dbinfo.name), false);
+ }
+ else
+ {
+ return deviceLink()->database(QString::fromLatin1(dbinfo.name));
+ }
+}
+
+
+// res gives us information whether the sync worked and the db might need to be
+// transferred to the handheld or not (and we just need to clean up the mess)
+bool DOCConduit::postSyncAction(PilotDatabase * database,
+ docSyncInfo &sinfo, bool res)
+{
+ FUNCTIONSETUP;
+ bool rs = true;
+
+ switch (sinfo.direction)
+ {
+ case eSyncPDAToPC:
+ // also reset the sync flags on the handheld
+#ifdef DEBUG
+ DEBUGKPILOT<<"Resetting sync flags for database "
+ <<sinfo.dbinfo.name<<endl;
+#endif
+ if (DOCConduitSettings::keepPDBsLocally() && !DOCConduitSettings::localSync())
+ {
+ PilotDatabase*db=deviceLink()->database(
+ QString::fromLatin1(sinfo.dbinfo.name));
+#ifdef DEBUG
+ DEBUGKPILOT<<"Middle 1 Resetting sync flags for database "
+ <<sinfo.dbinfo.name<<endl;
+#endif
+ if (db)
+ {
+ db->resetSyncFlags();
+ KPILOT_DELETE(db);
+ }
+ }
+#ifdef DEBUG
+ DEBUGKPILOT<<"End Resetting sync flags for database "
+ <<sinfo.dbinfo.name<<endl;
+#endif
+ break;
+ case eSyncPCToPDA:
+ if (DOCConduitSettings::keepPDBsLocally() && !DOCConduitSettings::localSync() && res)
+ {
+ // Copy the database to the palm
+ PilotLocalDatabase*localdb=dynamic_cast<PilotLocalDatabase*>(database);
+ if (localdb)
+ {
+#ifdef DEBUG
+ DEBUGKPILOT<<"Installing file "<<localdb->dbPathName()<<" ("
+ <<sinfo.handheldDB<<") to the handheld"<<endl;
+#endif
+ QString dbpathname=localdb->dbPathName();
+ // This deletes localdb as well, which is just a cast from database
+ KPILOT_DELETE(database);
+ if (!fHandle->installFiles(dbpathname, false))
+ {
+ rs = false;
+#ifdef DEBUG
+ DEBUGKPILOT<<"Could not install the database "<<dbpathname<<" ("
+ <<sinfo.handheldDB<<")"<<endl;
+#endif
+ }
+ }
+ }
+ default:
+ break;
+ }
+
+#ifdef DEBUG
+ DEBUGKPILOT<<"Vor KPILOT_DELETE(database)"<<endl;
+#endif
+
+ KPILOT_DELETE(database);
+#ifdef DEBUG
+ DEBUGKPILOT<<"End postSyncAction"<<endl;
+#endif
+ return rs;
+}
+
+
+
+void DOCConduit::cleanup()
+{
+ FUNCTIONSETUP;
+ DOCConduitSettings::setConvertedDOCfiles( fDBNames );
+ DOCConduitSettings::self()->writeConfig();
+
+ emit syncDone(this);
+}
+
diff --git a/kpilot/conduits/docconduit/doc-conduit.h b/kpilot/conduits/docconduit/doc-conduit.h
new file mode 100644
index 000000000..834002bea
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-conduit.h
@@ -0,0 +1,152 @@
+#ifndef _doc_CONDUIT_H
+#define _doc_CONDUIT_H
+/* doc-conduit.h KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+
+#include <plugin.h>
+
+class docSyncInfo;
+typedef QValueList<docSyncInfo> syncInfoList;
+
+typedef enum eSyncDirectionEnum {
+ eSyncNone,
+// eSyncAll,
+ eSyncPDAToPC,
+ eSyncPCToPDA,
+ eSyncDelete,
+ eSyncConflict
+ };
+typedef enum eTextStatus {
+ eStatNone=0,
+ eStatNew=1,
+ eStatChanged=2,
+ eStatBookmarksChanged=4,
+ eStatDeleted=8,
+ eStatDoesntExist=16
+ };
+
+
+QString dirToString(eSyncDirectionEnum dir);
+
+class DOCConduit:public ConduitAction {
+Q_OBJECT
+public:
+ eSyncDirectionEnum eSyncDirection;
+
+public:
+ DOCConduit(KPilotLink * o,
+ const char *n = 0L, const QStringList & a = QStringList());
+ virtual ~ DOCConduit();
+
+ bool encode(QStringList fileName, PilotDatabase * db);
+ bool decode(PilotDatabase * db, QString fileName);
+ virtual bool exec();
+protected:
+ virtual bool isCorrectDBTypeCreator(DBInfo dbinfo);
+ virtual const unsigned long dbtype();
+ virtual const unsigned long dbcreator();
+
+public slots:
+/** syncNextDB walks through all PalmDoc databases on the handheld and decides if they are supposed to be synced to the PC.
+ * syncNextDB and syncNextDOC fist build the list of all PalmDoc texts, and then the method syncDatabases does the actual sync. */
+ void syncNextDB();
+ void syncNextTXT();
+ void checkPDBFiles();
+ void checkDeletedDocs();
+ void resolve();
+ void syncDatabases();
+ void cleanup();
+
+ private:
+ /**
+ * Read the global KPilot config file for settings
+ * particular to the docConduit conduit.
+ */
+ void readConfig();
+
+ /**
+ * Check if the database needs to be synced at all.
+ */
+ bool needsSync(docSyncInfo &sinfo);
+ /**
+ * If necessary, copy the database from the palm to a local dir.
+ * Also initialize the docDBInfo that will be passed to the docconverter
+ */
+ PilotDatabase *preSyncAction(docSyncInfo &sinfo) const;
+
+ bool doSync(docSyncInfo &sinfo);
+ /**
+ * Clean up after the sync. The bool parameter res tells
+ * the function if the conversion was successful or not
+ */
+ bool postSyncAction(PilotDatabase * dbinfo, docSyncInfo &sinfo, bool res = true);
+
+ bool pcTextChanged(QString txtfn);
+ bool hhTextChanged(PilotDatabase*docdb);
+
+ /** Opens the database with name dbname. For a local sync, this will be a
+ * PilotLocalDatabase, otherwise it will be a database on the serial device
+ * (i.e. an object of class PilotSerialDatabase) */
+ PilotDatabase *openDOCDatabase(const QString &dbname);
+
+ QString constructPDBFileName(QString name);
+ QString constructTXTFileName(QString name);
+
+ eSyncDirectionEnum eConflictResolution;
+ int fTXTBookmarks, fPDBBookmarks;
+ QStringList fDBListSynced;
+ QStringList fDBNames;
+ syncInfoList fSyncInfoList;
+ syncInfoList::Iterator fSyncInfoListIterator;
+ long int dbnr;
+
+ QStringList docnames;
+ QStringList::Iterator dociterator;
+};
+
+class docSyncInfo
+{
+public:
+ docSyncInfo(QString hhDB=QString(), QString txtfn=QString(), QString pdbfn=QString(), eSyncDirectionEnum dir=eSyncNone)
+ {
+ handheldDB=hhDB;
+ txtfilename=txtfn;
+ pdbfilename=pdbfn;
+ direction=dir;
+ fPCStatus=eStatNone;
+ fPalmStatus=eStatNone;
+ };
+ ~docSyncInfo(){};
+ QString handheldDB, txtfilename, pdbfilename;
+ DBInfo dbinfo;
+ eSyncDirectionEnum direction;
+ eTextStatus fPCStatus, fPalmStatus;
+};
+
+
+#endif
diff --git a/kpilot/conduits/docconduit/doc-conflictdialog.cc b/kpilot/conduits/docconduit/doc-conflictdialog.cc
new file mode 100644
index 000000000..7dafd9b66
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-conflictdialog.cc
@@ -0,0 +1,182 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+#include "options.h"
+#include "doc-conflictdialog.moc"
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qbuttongroup.h>
+#include <kmessagebox.h>
+#include <qtimer.h>
+#include <qtable.h>
+#include <qcombobox.h>
+#include <qscrollview.h>
+
+
+ResolutionDialog::ResolutionDialog( QWidget* parent, const QString& caption, syncInfoList*sinfo, KPilotLink*lnk )
+ : KDialogBase( parent, "resolutionDialog", true, caption, KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, true), tickleTimer(0L), fHandle(lnk) {
+ FUNCTIONSETUP;
+ syncInfo=sinfo;
+ hasConflicts=false;
+
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
+
+ // First, insert the texts on top:
+ textLabel1 = new QLabel(i18n("Here is a list of all text files and DOC databases the conduit found. The conduit tried to determine the correct sync direction, but for databases in bold red letters a conflict occurred (i.e. the text was changed both on the desktop and on the handheld). For these databases please specify which version is the current one."), page);
+ textLabel1->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ topLayout->addWidget(textLabel1);
+
+ textLabel2 = new QLabel(i18n("You can also change the sync direction for databases without a conflict." ), page );
+ textLabel2->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) );
+ topLayout->addWidget(textLabel2);
+
+ resolutionGroupBox = new QGroupBox(i18n("DOC Databases"), page );
+ QVBoxLayout*playout = new QVBoxLayout(resolutionGroupBox);
+ QScrollView* sv = new QScrollView(resolutionGroupBox);
+ playout->addWidget(sv);
+ sv->setResizePolicy(QScrollView::AutoOneFit);
+ sv->setHScrollBarMode(QScrollView::AlwaysOff);
+ sv->setMargin(5);
+ QFrame* big_box = new QFrame(sv->viewport());
+ sv->addChild(big_box);
+
+
+ resolutionGroupBoxLayout = new QGridLayout( big_box, syncInfo->size(), 3 );
+ resolutionGroupBoxLayout->setAlignment( Qt::AlignTop );
+
+ // Invisible button group for the information buttons to use the same slot for all of them (see Dallheimer's book, page 309f)
+ QButtonGroup *bgroup = new QButtonGroup( this );
+ bgroup->hide();
+ QObject::connect(bgroup, SIGNAL(clicked(int)), this, SLOT(slotInfo(int)));
+
+ if (syncInfo) {
+ DEBUGKPILOT<<"Adding resolution options for the databases "<<endl;
+ syncInfoList::Iterator it;
+ int nr=0;
+ DEBUGKPILOT<<"We're having "<<(*syncInfo).size()<<" entries in the database list"<<endl;
+ for (it=syncInfo->begin(); it!=syncInfo->end(); ++it ) {
+ docSyncInfo si=(*it);
+ conflictEntry cE;
+ cE.index=nr;
+ cE.conflict=(si.direction==eSyncConflict);
+ DEBUGKPILOT<<"Adding "<<si.handheldDB<<" to the conflict resolution dialog"<<endl;
+
+ QString text=si.handheldDB;
+ if (cE.conflict) {
+ text=CSL1("<qt><b><font color=red>")+text+CSL1("</font></b></qt>");
+ DEBUGKPILOT<<"We have a conflict for database "<<si.handheldDB<<endl;
+ hasConflicts=true;
+ }
+ cE.dbname=new QLabel(text, big_box);
+ resolutionGroupBoxLayout->addWidget( cE.dbname, cE.index, 0 );
+
+ cE.resolution=new QComboBox( FALSE, big_box);
+ cE.resolution->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7,
+ (QSizePolicy::SizeType)0, 0, 0,
+ cE.resolution->sizePolicy().hasHeightForWidth() ) );
+ cE.resolution->clear();
+ cE.resolution->insertItem( i18n( "No Sync" ) );
+ cE.resolution->insertItem( i18n( "Sync Handheld to PC" ) );
+ cE.resolution->insertItem( i18n( "Sync PC to Handheld" ) );
+ cE.resolution->insertItem( i18n( "Delete Both Databases" ) );
+ cE.resolution->setCurrentItem((int)si.direction);
+ resolutionGroupBoxLayout->addWidget( cE.resolution, cE.index, 1);
+
+ cE.info = new QPushButton( i18n("More Info..."), big_box );
+ resolutionGroupBoxLayout->addWidget(cE.info, cE.index, 2);
+ bgroup->insert(cE.info);
+
+ conflictEntries.append(cE);
+ ++nr;
+ }
+ } else {
+ WARNINGKPILOT << "The list of text files is not available to the resolution dialog." << endl;
+ }
+
+
+ topLayout->addWidget( resolutionGroupBox );
+ resize( QSize(600, 480).expandedTo(minimumSizeHint()) );
+
+ if (fHandle) tickleTimer=new QTimer(this, "TickleTimer");
+ if (tickleTimer) {
+ connect( tickleTimer, SIGNAL(timeout()), this, SLOT(_tickle()) );
+ tickleTimer->start( 10000 ); // tickle the palm every 10 seconds to prevent a timeout until the sync is really finished.
+ }
+
+}
+
+/*
+ * Destroys the object and frees any allocated resources
+ */
+ResolutionDialog::~ResolutionDialog()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+
+/* virtual slot */ void ResolutionDialog::slotOk() {
+ FUNCTIONSETUP;
+ QValueList<conflictEntry>::Iterator ceIt;
+ for (ceIt=conflictEntries.begin(); ceIt!=conflictEntries.end(); ++ceIt) {
+ (*syncInfo)[(*ceIt).index].direction=(eSyncDirectionEnum)((*ceIt).resolution->currentItem());
+ }
+ KDialogBase::slotOk();
+}
+
+QString eTextStatusToString(eTextStatus stat) {
+ switch(stat) {
+ case eStatNone: return i18n("unchanged");
+ case eStatNew: return i18n("new");
+ case eStatChanged: return i18n("changed");
+ case eStatBookmarksChanged: return i18n("only bookmarks changed");
+ case eStatDeleted: return i18n("deleted");
+ case eStatDoesntExist: return i18n("does not exist");
+ default: return i18n("unknown");
+ }
+}
+
+void ResolutionDialog::slotInfo(int index) {
+ FUNCTIONSETUP;
+ conflictEntry cE=conflictEntries[index];
+ int ix=cE.index;
+ if (!syncInfo) return;
+ docSyncInfo si=(*syncInfo)[ix];
+ QString text=i18n("Status of the database %1:\n\n").arg(si.handheldDB);
+ text+=i18n("Handheld: %1\n").arg(eTextStatusToString(si.fPalmStatus));
+ text+=i18n("Desktop: %1\n").arg(eTextStatusToString(si.fPCStatus));
+
+ KMessageBox::information(this, text, i18n("Database information"));
+}
+
+
+void ResolutionDialog::_tickle() {
+ FUNCTIONSETUP;
+ if (fHandle) fHandle->tickle();
+}
diff --git a/kpilot/conduits/docconduit/doc-conflictdialog.h b/kpilot/conduits/docconduit/doc-conflictdialog.h
new file mode 100644
index 000000000..f8ad8caf7
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-conflictdialog.h
@@ -0,0 +1,83 @@
+#ifndef CONFLICTDIALOG_H
+#define CONFLICTDIALOG_H
+/* doc-conflictdialog.h KPilot
+**
+** Copyright (C) 2002-2003 by Reinhold Kainhofer
+**
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+
+#include <kdialogbase.h>
+#include "doc-conduit.h"
+
+
+class QComboBox;
+class QGridLayout;
+class QGroupBox;
+
+class QLabel;
+class QPushButton;
+class QTimer;
+class KPilotLink;
+
+
+typedef struct conflictEntry {
+ QLabel*dbname;
+ QComboBox* resolution;
+ QPushButton*info;
+ int index;
+ bool conflict;
+};
+
+
+class ResolutionDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ ResolutionDialog( QWidget* parent=0, const QString& caption=i18n("Resolution Dialog"), syncInfoList*sinfo=0L, KPilotLink*lnk=0L);
+ ~ResolutionDialog();
+
+ bool hasConflicts;
+public slots:
+ void _tickle();
+protected:
+ QTimer* tickleTimer;
+ KPilotLink* fHandle;
+
+protected:
+ QGroupBox* resolutionGroupBox;
+ QGridLayout*resolutionGroupBoxLayout;
+
+ syncInfoList*syncInfo;
+ QValueList<conflictEntry> conflictEntries;
+ QLabel *textLabel1,*textLabel2;
+
+protected slots:
+ virtual void slotOk();
+ void slotInfo(int index);
+
+};
+
+#endif // CONFLICTDIALOG_H
diff --git a/kpilot/conduits/docconduit/doc-factory.cc b/kpilot/conduits/docconduit/doc-factory.cc
new file mode 100644
index 000000000..3d2a16b11
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-factory.cc
@@ -0,0 +1,116 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the factory for the doc-conduit plugin.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+#include "options.h"
+#include "doc-factory.moc"
+#include "doc-factory.h"
+
+#include <kinstance.h>
+#include <kaboutdata.h>
+#include <kpilotlink.h>
+
+#include "doc-conduit.h"
+#include "doc-setup.h"
+
+
+extern "C" {
+ void *init_conduit_doc() {
+ return new DOCConduitFactory;
+ }
+}
+
+
+
+// A number of static variables
+KAboutData * DOCConduitFactory::fAbout = 0L;
+
+const char *DOCConduitFactory::dbDOCtype = "TEXt";
+const char *DOCConduitFactory::dbDOCcreator = "REAd";
+
+
+
+DOCConduitFactory::DOCConduitFactory(QObject * p, const char *n):
+KLibFactory(p, n)
+{
+ FUNCTIONSETUP;
+ fInstance = new KInstance("docconduit");
+ fAbout =new KAboutData("docconduit",
+ I18N_NOOP("Palm DOC Conduit for KPilot"), KPILOT_VERSION,
+ I18N_NOOP("Configures the DOC Conduit for KPilot"),
+ KAboutData::License_GPL, "(C) 2002, Reinhold Kainhofer");
+
+ fAbout->addAuthor("Reinhold Kainhofer",
+ I18N_NOOP("Maintainer"), "[email protected]",
+ "http://reinhold.kainhofer.com");
+}
+
+DOCConduitFactory::~DOCConduitFactory()
+{
+ FUNCTIONSETUP;
+ KPILOT_DELETE(fInstance);
+ KPILOT_DELETE(fAbout);
+}
+
+
+/* virtual */ QObject * DOCConduitFactory::createObject(QObject * p,
+ const char *n, const char *c, const QStringList & a)
+{
+ FUNCTIONSETUP;
+
+#ifdef DEBUG
+ DEBUGKPILOT << fname <<": Creating object of class " <<c <<endl;
+#endif
+ if (qstrcmp(c, "ConduitConfigBase") == 0)
+ {
+ QWidget *w = dynamic_cast<QWidget *>(p);
+ if (w)
+ {
+ return new DOCWidgetConfig(w,n);
+ }
+ else
+ {
+ WARNINGKPILOT << "Couldn't cast parent to widget." << endl;
+ return 0L;
+ }
+ }
+ if (qstrcmp(c, "SyncAction") == 0)
+ {
+ KPilotLink * d = dynamic_cast < KPilotLink * >(p);
+ if (d)
+ {
+ return new DOCConduit(d, n, a);
+ }
+ else
+ {
+ WARNINGKPILOT << "Couldn't cast parent to KPilotLink" <<endl;
+ return 0L;
+ }
+ }
+ return 0L;
+}
+
diff --git a/kpilot/conduits/docconduit/doc-factory.h b/kpilot/conduits/docconduit/doc-factory.h
new file mode 100644
index 000000000..c848777a0
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-factory.h
@@ -0,0 +1,74 @@
+#ifndef _DOC_FACTORY_H
+#define _DOC_FACTORY_H
+
+/* doc-factory.h KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the factory for the doc-conduit plugin.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+#include <klibloader.h>
+
+class KInstance;
+class KAboutData;
+
+
+class DOCConduitFactory:public KLibFactory
+{
+
+Q_OBJECT
+
+public:
+ DOCConduitFactory(QObject * = 0L, const char * = 0L);
+ virtual ~ DOCConduitFactory();
+
+ static KAboutData *about() {
+ return fAbout;
+ };
+
+ static const char
+ *fDBListSynced;
+ static const char *dbDOCtype;
+ static const char *dbDOCcreator;
+
+
+protected:
+ virtual QObject * createObject(QObject * parent = 0,
+ const char *name = 0,
+ const char *classname = "QObject",
+ const QStringList & args = QStringList());
+
+private:
+ KInstance * fInstance;
+ static KAboutData *fAbout;
+};
+
+
+extern "C" {
+ void *init_libdocconduit();
+}
+
+
+#endif
diff --git a/kpilot/conduits/docconduit/doc-setup.cc b/kpilot/conduits/docconduit/doc-setup.cc
new file mode 100644
index 000000000..a6de2d2ad
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-setup.cc
@@ -0,0 +1,136 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the setup dialog for the doc-conduit plugin.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+#include "options.h"
+
+#include <qtabwidget.h>
+#include <qcheckbox.h>
+#include <qbuttongroup.h>
+#include <qcombobox.h>
+
+#include <kconfig.h>
+#include <kurlrequester.h>
+#include <kcharsets.h>
+
+#include "doc-setupdialog.h"
+#include "doc-factory.h"
+#include "doc-setup.h"
+#include "docconduitSettings.h"
+
+
+DOCWidgetConfig::DOCWidgetConfig(QWidget * w, const char *n):
+ ConduitConfigBase(w, n),
+ fConfigWidget(new DOCWidget(w))
+{
+ FUNCTIONSETUP;
+
+ fWidget=fConfigWidget;
+
+ QStringList l = KGlobal::charsets()->descriptiveEncodingNames();
+ for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it)
+ {
+ fConfigWidget->fEncoding->insertItem(*it);
+ }
+
+ fConfigWidget->fTXTDir->setMode(KFile::Directory);
+ fConfigWidget->fPDBDir->setMode(KFile::Directory);
+ ConduitConfigBase::addAboutPage(fConfigWidget->tabWidget,DOCConduitFactory::about());
+
+ fConduitName=i18n("Palm DOC");
+
+#define CMOD(a,b) connect(fConfigWidget->a,SIGNAL(b),this,SLOT(modified()))
+ CMOD(fTXTDir,textChanged(const QString &));
+ CMOD(fPDBDir,textChanged(const QString &));
+ CMOD(fkeepPDBLocally,clicked());
+ CMOD(fConflictResolution,clicked(int));
+ CMOD(fConvertBookmarks,stateChanged(int));
+ CMOD(fBookmarksBmk,stateChanged(int));
+ CMOD(fBookmarksInline,stateChanged(int));
+ CMOD(fBookmarksEndtags,stateChanged(int));
+ CMOD(fCompress,stateChanged(int));
+ CMOD(fSyncDirection,clicked(int));
+ CMOD(fNoConversionOfBmksOnly,stateChanged(int));
+ CMOD(fAlwaysUseResolution,stateChanged(int));
+ CMOD(fPCBookmarks,clicked(int));
+ CMOD(fEncoding,textChanged(const QString &));
+#undef CMOD
+
+ fConfigWidget->adjustSize();
+}
+
+/* virtual */ void DOCWidgetConfig::commit()
+{
+ FUNCTIONSETUP;
+
+ DOCConduitSettings::setTXTDirectory( fConfigWidget->fTXTDir->url() );
+ DOCConduitSettings::setPDBDirectory( fConfigWidget->fPDBDir->url() );
+
+ DOCConduitSettings::setKeepPDBsLocally( fConfigWidget->fkeepPDBLocally->isChecked());
+ DOCConduitSettings::setConflictResolution( fConfigWidget->fConflictResolution->id(
+ fConfigWidget->fConflictResolution->selected()) );
+ DOCConduitSettings::setConvertBookmarks(fConfigWidget->fConvertBookmarks->isChecked());
+ DOCConduitSettings::setBmkFileBookmarks(fConfigWidget->fBookmarksBmk->isChecked());
+ DOCConduitSettings::setInlineBookmarks(fConfigWidget->fBookmarksInline->isChecked());
+ DOCConduitSettings::setEndtagBookmarks(fConfigWidget->fBookmarksEndtags->isChecked());
+ DOCConduitSettings::setCompress(fConfigWidget->fCompress->isChecked());
+ DOCConduitSettings::setSyncDirection(fConfigWidget->fSyncDirection->id(
+ fConfigWidget->fSyncDirection->selected()));
+ DOCConduitSettings::setIgnoreBmkChanges(fConfigWidget->fNoConversionOfBmksOnly->isChecked());
+ DOCConduitSettings::setAlwaysShowResolutionDialog(fConfigWidget->fAlwaysUseResolution->isChecked());
+ DOCConduitSettings::setBookmarksToPC( fConfigWidget->fPCBookmarks->id(
+ fConfigWidget->fPCBookmarks->selected()) );
+ DOCConduitSettings::setEncoding( fConfigWidget->fEncoding->currentText() );
+
+ DOCConduitSettings::self()->writeConfig();
+ unmodified();
+}
+
+/* virtual */ void DOCWidgetConfig::load()
+{
+ FUNCTIONSETUP;
+ DOCConduitSettings::self()->readConfig();
+
+ fConfigWidget->fTXTDir->setURL( DOCConduitSettings::tXTDirectory() );
+ fConfigWidget->fPDBDir->setURL( DOCConduitSettings::pDBDirectory() );
+ fConfigWidget->fkeepPDBLocally->setChecked( DOCConduitSettings::keepPDBsLocally() );
+ fConfigWidget->fConflictResolution->setButton(DOCConduitSettings::conflictResolution() );
+ fConfigWidget->fConvertBookmarks->setChecked(DOCConduitSettings::convertBookmarks() );
+ fConfigWidget->fBookmarksBmk->setChecked(DOCConduitSettings::bmkFileBookmarks() );
+ fConfigWidget->fBookmarksInline->setChecked(DOCConduitSettings::inlineBookmarks() );
+ fConfigWidget->fBookmarksEndtags->setChecked(DOCConduitSettings::endtagBookmarks() );
+ fConfigWidget->fCompress->setChecked(DOCConduitSettings::compress() );
+ fConfigWidget->fSyncDirection->setButton(DOCConduitSettings::syncDirection() );
+
+ fConfigWidget->fNoConversionOfBmksOnly->setChecked( DOCConduitSettings::ignoreBmkChanges() );
+ fConfigWidget->fAlwaysUseResolution->setChecked( DOCConduitSettings::alwaysShowResolutionDialog() );
+
+ fConfigWidget->fPCBookmarks->setButton(DOCConduitSettings::bookmarksToPC() );
+ fConfigWidget->fEncoding->setCurrentText(DOCConduitSettings::encoding() );
+ unmodified();
+}
+
diff --git a/kpilot/conduits/docconduit/doc-setup.h b/kpilot/conduits/docconduit/doc-setup.h
new file mode 100644
index 000000000..470585e01
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-setup.h
@@ -0,0 +1,47 @@
+#ifndef _DOC_DOC_SETUP_H
+#define _DOC_DOC_SETUP_H
+/* doc-setup.h KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This file defines the widget and behavior for the config dialog
+** of the doc conduit.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+#include "plugin.h"
+
+class DOCWidget;
+
+class DOCWidgetConfig : public ConduitConfigBase
+{
+public:
+ DOCWidgetConfig(QWidget *, const char *);
+ virtual void commit();
+ virtual void load();
+protected:
+ DOCWidget *fConfigWidget;
+} ;
+
+
+#endif
diff --git a/kpilot/conduits/docconduit/doc-setupdialog.ui b/kpilot/conduits/docconduit/doc-setupdialog.ui
new file mode 100644
index 000000000..cbb45e344
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc-setupdialog.ui
@@ -0,0 +1,557 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>DOCWidget</class>
+<author>Reinhold Kainhofer</author>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>Form2</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>564</width>
+ <height>266</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </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>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Text files:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fTXTDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter here, or select clicking the file picker button, the name and location of the folder used to find and synchronize text files. All files with extension .txt located in this folder will be synced to Palm DOC databases in your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>fkeepPDBLocally</cstring>
+ </property>
+ <property name="text">
+ <string>Local co&amp;py:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box if you want to save a copy of the Palm DOC databases (.pdb files) on your PC.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="0" column="1">
+ <property name="name">
+ <cstring>fTXTDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter here, or select clicking the file picker button, the name and location of the folder used to find and synchronize text files. All files with extension .txt located in this folder will be synced to Palm DOC databases in your handheld.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QButtonGroup" row="2" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fSyncDirection</cstring>
+ </property>
+ <property name="title">
+ <string>Synchronization Mode</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>RadioButton3</cstring>
+ </property>
+ <property name="text">
+ <string>Sync only P&amp;C to PDA</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>2</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize texts changed in your PC to Palm DOC databases in your handheld. Palm DOC databases modified in the handheld will not be converted to text files, but texts changed in the PC will be converted to the Palm DOC databases.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>RadioButton2</cstring>
+ </property>
+ <property name="text">
+ <string>Sync only P&amp;DA to PC</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize the changes made to Palm DOC databases in your handheld to the PC text files. Palm DOC databases modified in the handheld will be converted to text files, but texts changed in the PC will not be converted to the Palm DOC databases.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>RadioButton1</cstring>
+ </property>
+ <property name="text">
+ <string>Sync &amp;all</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Select this option to synchronize the file texts in your PC to Palm DOC databases in your handheld. Palm DOC databases modified in the handheld will be converted to text files, and texts changed in the PC will be converted to the Palm DOC databases, keeping both versions in sync.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <spacer row="3" column="1">
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KURLRequester" row="1" column="1">
+ <property name="name">
+ <cstring>fPDBDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Enter here, or select clicking the file picker button, the name and location of the folder where copies of the handheld databases are kept (.pdb files). Local copies are only made if the box is checked as well.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>PC -&gt; Handheld</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>fCompress</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Compress</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Check this box, if the text should be compressed on the handheld to save memory. Most doc reader on the handheld support compressed texts.</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC format supports compressing the text to save memory. Check this box to enable text compression, so the resulting Palm DOC database will consume about 50% less memory than in uncompressed state. Almost all DOC readers on the Palm support compressed texts.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>fConvertBookmarks</cstring>
+ </property>
+ <property name="text">
+ <string>Convert &amp;bookmarks</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to enable bookmark creation when converting text files to Palm DOC databases. Most doc readers support bookmarks. In order to create a bookmark, it is necessary to to provide the location in the text where the bookmark should be set and the bookmark title, in at least one of the formats listed below.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer row="6" column="2">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>fBookmarksInline</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Inline tags in text</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this box to create bookmarks from inline tags in the text. The inline tag consist of tags in the form &lt;* bookmarktext *&gt;. The bookmark location is set using the location of the inline tag in the text, and the name is the text between the &lt;* and the *&gt;. The inline tag (&lt;*...*&gt;) will be removed from the text.</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Encoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fEncoding</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1">
+ <property name="name">
+ <cstring>fBookmarksEndtags</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Tags at end of text</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this box to convert tags of the form &lt;bookmarkname&gt; at the end of the text to bookmarks. The text inside the tag ("bookmarkname") will be searched in the text, and whenever found, a bookmark will be set there. The endtags &lt;...&gt; will then be removed from the end of the text.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="4" column="1">
+ <property name="name">
+ <cstring>fBookmarksBmk</cstring>
+ </property>
+ <property name="text">
+ <string>Regular &amp;expressions in .bmk file</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to use regular expressions in a file to search the text for bookmarks. The file should have the same name as the text file, but should end in .bmk instead of .txt (for instance, the regular expression file for textname.txt should be textname.bmk). See the documentation for a description of the format of the bmk file.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="5" column="1">
+ <property name="name">
+ <cstring>fEncoding</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Handheld -&gt; PC</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer16</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="1" column="0">
+ <property name="name">
+ <cstring>fNoConversionOfBmksOnly</cstring>
+ </property>
+ <property name="text">
+ <string>Do not convert, if text unchanged (only bookmarks)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to avoid syncing the text on the handheld to the PC if you only changed the bookmarks on the handheld (but not the text).&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>fPCBookmarks</cstring>
+ </property>
+ <property name="title">
+ <string>Convert Bookmarks</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioButton8</cstring>
+ </property>
+ <property name="text">
+ <string>Do &amp;not convert bookmarks</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to avoid converting Palm DOC bookmarks to inline tags or to a bookmark file.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioButton11</cstring>
+ </property>
+ <property name="text">
+ <string>Convert into .bm &amp;file</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>1</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to convert the Palm DOC database bookmarks to a separate file, in the bmk format (see more about this format in the documentation). The resulting bookmark file shares the same filename as the resulting .txt file, but ends in .bmk instead. This approach creates a clean text file and a bookmark file.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>radioButton9</cstring>
+ </property>
+ <property name="text">
+ <string>Convert as &amp;inline tags</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>2</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to convert the Palm DOC database bookmarks to inline tags, in the form &amp;lt;* BookmarkName *&amp;gt;. These tags are inserted in the text in the position marked by the bookmark, and the text inside the tag corresponds to the bookmark name. Inline tags are easy to create, delete, move and edit.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Conflicts</string>
+ </attribute>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QButtonGroup">
+ <property name="name">
+ <cstring>fConflictResolution</cstring>
+ </property>
+ <property name="title">
+ <string>Conflict Resolution</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>If the same text was changed on the PC and the handheld, which of the two versions should be used as the new version?</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC conduit does not feature merging the modifications when a text is changed both in the handheld and in the computer. Therefore, the choice is between working with the files out of sync, or discarding the changes in one of them.&lt;/qt&gt;</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioButton12</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;No resolution</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC conduit does not feature merging the modifications when a text is changed both in the handheld and in the computer. Therefore, when conflicts appear, the choice is between working with the files out of sync, or discarding the changes in one of them. Select this option to prevent KPilot from overwriting your modifications.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>RadioButton5</cstring>
+ </property>
+ <property name="text">
+ <string>P&amp;DA overrides</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>1</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC conduit does not feature merging the modifications when a text is changed both in the handheld and in the computer. Therefore, when conflicts appear, the choice is between working with the files out of sync, or discarding the changes in one of them. Select this option to make the PDA version overwrite the PC version in case of conflict.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>RadioButton4</cstring>
+ </property>
+ <property name="text">
+ <string>P&amp;C overrides</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>2</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC conduit does not feature merging the modifications when a text is changed both in the handheld and in the computer. Therefore, when conflicts appear, the choice is between working with the files out of sync, or discarding the changes in one of them. Select this option to make the PC version overwrite the PDA version in case of conflict.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="0">
+ <property name="name">
+ <cstring>RadioButton7</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Ask the user</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="buttonGroupId">
+ <number>4</number>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;The Palm DOC conduit does not feature merging the modifications when a text is changed both in the handheld and in the computer. Therefore, when conflicts appear, the choice is between working with the files out of sync, or discarding the changes in one of them. Select this option to show the resolution dialog to let the user decide on a case by case basis.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>fAlwaysUseResolution</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Always show the resolution dialog</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;qt&gt;Check this box to force the resolution dialog to appear even when there are no conflicts.&lt;/qt&gt;</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksInline</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksEndtags</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksBmk</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>fkeepPDBLocally</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fPDBDir</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>fTXTDir</tabstop>
+ <tabstop>fkeepPDBLocally</tabstop>
+ <tabstop>fPDBDir</tabstop>
+ <tabstop>fCompress</tabstop>
+ <tabstop>fConvertBookmarks</tabstop>
+ <tabstop>fBookmarksInline</tabstop>
+ <tabstop>fBookmarksEndtags</tabstop>
+ <tabstop>fBookmarksBmk</tabstop>
+ <tabstop>radioButton11</tabstop>
+ <tabstop>fNoConversionOfBmksOnly</tabstop>
+ <tabstop>RadioButton7</tabstop>
+ <tabstop>fAlwaysUseResolution</tabstop>
+ <tabstop>tabWidget</tabstop>
+ <tabstop>RadioButton1</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>
diff --git a/kpilot/conduits/docconduit/doc_conduit.desktop b/kpilot/conduits/docconduit/doc_conduit.desktop
new file mode 100644
index 000000000..65f1ce425
--- /dev/null
+++ b/kpilot/conduits/docconduit/doc_conduit.desktop
@@ -0,0 +1,59 @@
+[Desktop Entry]
+Type=Service
+Comment=Adds text files to your handheld, suitable for DOC readers.
+Comment[af]=Voeg teks lêers by jou draagbare toestel in DOC leser formaat.
+Comment[bg]=Добавяне на текстови файлове към мобилно устройство.
+Comment[ca]=Afegeix fitxers de text a la vostra agenda, apropiat per a lectors de DOC.
+Comment[cs]=Přidává textové soubory do vašeho Pilotu, výhodné pro čtenáře dokumentů.
+Comment[da]=Tilføjer tekstfiler til din håndholdte, passende for DOC-læsere.
+Comment[de]=Gibt Textdateien in Taschencomputer ein, passend für DOC-Leser.
+Comment[el]=Προσθέτει αρχεία κειμένου στον υπολογιστή παλάμης σας, κατάλληλο για αναγνώστες DOC.
+Comment[es]=Añade archivos de texto a su agenda electrónica. Compatible con los lectores DOC.
+Comment[et]=Lisab DOC-riiderile sobilikud tekstifailid sinu pihuseadmele.
+Comment[eu]=Zure agenda elektronikora DOC irakurleentzako aproposak diren testu fitxategiak gehitzen ditu.
+Comment[fa]=پرونده‌های متن را به دستی شما اضافه می‌کند، که برای خوانندگان DOC مفید است.
+Comment[fi]=Lisää tekstitiedostoja taskutietokoneeseen. Tämä on käyttökelpoinen DOC-lukijoille.
+Comment[fr]=Ajoute des fichiers texte à votre Palm, approprié pour les lecteurs de DOC.
+Comment[fy]=Heakket tekstfjilden ta oan jo handheld, geskikt faor DOC-lêzers.
+Comment[gl]=Engade ficheiros de texto ao seu aparello de man, axeitado para os lectores DOC.
+Comment[hu]=Szöveges fájlok hozzáadása a kézi számítógéphez, DOC-olvasók számára.
+Comment[is]=Bætir textaskrám, sem hægt er að lesa í DOC lesara, við lófatölvuna þína.
+Comment[it]=Aggiunge file di testo al tuo Pilot, adatti per lettori DOC.
+Comment[ja]=テキストファイルを DOC リーダーに適した形式でハンドヘルドに追加します。
+Comment[ka]=უმატებს ტექსტურ ფაილებს თქვენს პროტატიულ მოწყობილობას, რომელიც შესაფერისია DOC წამკითხავებისთვის
+Comment[kk]=DOC файлды оқи алатын қалта құрылғыға мәтінді көшіру.
+Comment[km]=បន្ថែម​ឯកសារ​អត្ថបទ​ទៅ​ឧបករណ៍​យួរ​ដៃ​របស់​អ្នក (សមស្រប​សម្រាប់​កម្មវិធី​អាន DOC) ។
+Comment[lt]=Prideda teksto bylas prie Jūsų nešiojamos knygelės, tinka DOC skaityklėms.
+Comment[ms]=Menambah fail teks ke komputer telapak, sesuai dengan pembaca DOC.
+Comment[nb]=Legger til tekstfiler på PDA-en, som passer for DOC-lesere.
+Comment[nds]=Föögt Textdateien op den Handreekner to, de för DOC-Kiekers passt.
+Comment[ne]=DOC रिडरका लागि उपयुक्त हुने पाठ फाइल तपाईँको ह्यान्डहेल्डमा थप्दछ ।
+Comment[nl]=Voegt tekstvelden toe aan uw handheld, geschikt voor DOC-lezers.
+Comment[nn]=Legg til tekstfiler på den handhaldne, passar til DOC-lesarar.
+Comment[pl]=Dodaje pliki tekstowe do Twojego palmtopa, w postaci odpowiedniej dla przeglądarek DOC.
+Comment[pt]=Adiciona ficheiros de texto ao seu PDA, indicado para os leitores de DOC.
+Comment[pt_BR]=Adiciona arquivos de texto ao seu handheld, adequado para leitors de DOC.
+Comment[ru]=Перенос текстовых файлов на КПК.
+Comment[sk]=Pridá textové súbory do ručného zariadenia, vhodné pre čítanie DOC.
+Comment[sl]=V vaš ročni računalnik doda besedilne datoteke, primerne za bralnike DOC.
+Comment[sr]=Додаје текстуалне фајлове вашем ручном рачунару, погодне за DOC читаче.
+Comment[sr@Latn]=Dodaje tekstualne fajlove vašem ručnom računaru, pogodne za DOC čitače.
+Comment[sv]=Lägger till textfiler i en handdator, lämpliga för DOC-läsare.
+Comment[ta]=DOC படிப்பவர்களுக்கு பொருத்தமான உங்கள் பைலட்டுக்குரிய உரை கோப்புகளை சேர்க்கும்
+Comment[tr]=Metin dosyalarını el bilgisayarınıza ekler, DOC biçimi okuyucuları için uygundur.
+Comment[uk]=Додає текстові файли до вашого кишенькового пристрою так, що вони читатимуться у переглядачах DOC.
+Comment[zh_CN]=将文本文件添加到您的手持设备中,以便适合 DOC 阅读程序。
+Comment[zh_TW]=新增文字到您的 handheld。
+Name=Palm DOC
+Name[ca]=DOC de Palm
+Name[cy]=DOC Palm
+Name[de]=Palm-DOC
+Name[fa]=رایانۀ جیبی DOC
+Name[hi]=पॉम डॉक
+Name[nds]=Palm-DOC
+Name[ne]=पाल्म DOC
+Name[pt]=DOC do Palm
+Name[ta]=பாம் ஆவணம்
+Implemented=file
+ServiceTypes=KPilotConduit
+X-KDE-Library=conduit_doc
diff --git a/kpilot/conduits/docconduit/docconduit.kcfg b/kpilot/conduits/docconduit/docconduit.kcfg
new file mode 100644
index 000000000..6301f4595
--- /dev/null
+++ b/kpilot/conduits/docconduit/docconduit.kcfg
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="kpilot_docconduitrc"/>
+ <group name="General">
+ <entry name="TXTDirectory" key="TXT Directory" type="Path"/>
+ <entry name="PDBDirectory" key="PDB Directory" type="Path"/>
+ <entry name="KeepPDBsLocally" key="Keep PDBs locally" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="LocalSync" key="Sync only locally" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="ConflictResolution" key="Conflict Resolution" type="UInt">
+ <default>0</default>
+ </entry>
+ <entry name="ConvertBookmarks" key="Convert Bookmarks" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="BmkFileBookmarks" key="Bmk file bookmarks" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="InlineBookmarks" key="Inline bookmarks" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="EndtagBookmarks" key="Endtag bookmarks" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="Compress" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="SyncDirection" key="Sync Direction" type="UInt">
+ <default>1</default>
+ </entry>
+ <entry name="IgnoreBmkChanges" key="Ignore only bookmark changes" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="AlwaysShowResolutionDialog" key="Always show resolution dialog" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="BookmarksToPC" key="Bookmarks to PC" type="UInt">
+ <default>0</default>
+ </entry>
+ <entry name="ConvertedDOCfiles" key="Converted PalmDOCs" type="StringList">
+ <default></default>
+ </entry>
+ <entry name="Encoding" type="String">
+ <default>ISO8859-15</default>
+ </entry>
+ </group>
+
+</kcfg>
diff --git a/kpilot/conduits/docconduit/docconduitSettings.kcfgc b/kpilot/conduits/docconduit/docconduitSettings.kcfgc
new file mode 100644
index 000000000..2a9a3a0f7
--- /dev/null
+++ b/kpilot/conduits/docconduit/docconduitSettings.kcfgc
@@ -0,0 +1,7 @@
+File=docconduit.kcfg
+ClassName=DOCConduitSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/docconduit/kpalmdoc.cpp b/kpilot/conduits/docconduit/kpalmdoc.cpp
new file mode 100644
index 000000000..55956cf48
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc.cpp
@@ -0,0 +1,58 @@
+/* converter.cpp
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This is the main program of the KDE PalmDOC converter.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+#include "options.h"
+
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <kapplication.h>
+
+#include "kpalmdoc_dlg.h"
+
+
+
+int main(int argc, char *argv[])
+{
+
+ KAboutData about("converter", I18N_NOOP("KPalmDOC"), "-0.0.1",
+ "KPalmDOC - KDE Converter for PalmDOC texts.\n\n",
+ KAboutData::License_GPL, "(c) 2003, Reinhold Kainhofer");
+ about.addAuthor("Reinhold Kainhofer", I18N_NOOP("Main Developer"),
+ "[email protected]", "http://reinhold.kainhofer.com/Linux/");
+ about.addCredit("Adriaan de Groot", I18N_NOOP("Maintainer of KPilot"),
+ "[email protected]", "http://www.kpilot.org/");
+
+ KCmdLineArgs::init(argc, argv, &about);
+ KApplication::addCmdLineOptions();
+
+ KApplication app;
+ ConverterDlg *dlg=new ConverterDlg(0L, i18n("PalmDOC Converter"));
+ dlg->show();
+ return app.exec();
+}
+
diff --git a/kpilot/conduits/docconduit/kpalmdoc.desktop b/kpilot/conduits/docconduit/kpalmdoc.desktop
new file mode 100644
index 000000000..df897fb7d
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc.desktop
@@ -0,0 +1,65 @@
+# KDE Config File
+[Desktop Entry]
+Name=KPalmDOC
+Name[hi]=के-पॉम-डॉक
+Name[sv]=Kpalm DOC
+Name[ta]=கேகைdoc
+GenericName=PalmDOC Converter
+GenericName[af]=PalmDOC omskakelaar
+GenericName[bg]=Конвертиране на PalmDOC
+GenericName[bs]=PalmDOC konverter
+GenericName[ca]=Convertidor a PalmDOC
+GenericName[cs]=Konvertor PalmDoc
+GenericName[cy]=Trosiadydd PalmDOC
+GenericName[da]=PalmDOC konverterer
+GenericName[de]=PalmDOC-Konvertierung
+GenericName[el]=Μετατροπέας PalmDOC
+GenericName[eo]=PalmDOC-konvertilo
+GenericName[es]=Conversor de PalmDOC
+GenericName[et]=PalmDOC konverter
+GenericName[eu]=PalmDOC bihurtzailea
+GenericName[fa]=مبدل PalmDOC
+GenericName[fi]=PalmDOC-muunnin
+GenericName[fr]=Convertisseur PalmDOC
+GenericName[fy]=PalmDOC-oersetter
+GenericName[ga]=Tiontaire PalmDOC
+GenericName[gl]=Convertidor de PalmDOC
+GenericName[hi]=पॉम-डॉक परिवर्तक
+GenericName[hu]=PalmDOC-konverter
+GenericName[is]=PalmDOC umbreytir
+GenericName[it]=Convertitore PalmDOC
+GenericName[ja]= PalmDOC コンバータ
+GenericName[ka]=კონვერტორი PalmDOC
+GenericName[kk]=PalmDOC аударғышы
+GenericName[km]=កម្មវិធី​បម្លែង PalmDOC
+GenericName[lt]=PalmDOC konverteris
+GenericName[ms]=Penukar PalmDOC
+GenericName[nb]=PalmDOC-konvertering
+GenericName[nds]=PalmDOC-Ümwanneln
+GenericName[ne]=PalmDOC रुपान्तरणकर्ता
+GenericName[nl]=PalmDOC-conversie
+GenericName[nn]=PalmDOC-omformar
+GenericName[pl]=Konwerter formatu PalmDOC
+GenericName[pt]=Conversor de PalmDOC
+GenericName[pt_BR]=Conversor para PalmDOC
+GenericName[ro]=Convertor PalmDOC
+GenericName[ru]=Конвертер PalmDOC
+GenericName[sk]=PalmDOC prevod
+GenericName[sl]=Pretvornik v PalmDOC
+GenericName[sr]=PalmDOC конвертор
+GenericName[sr@Latn]=PalmDOC konvertor
+GenericName[sv]=Konvertering av Palm DOC
+GenericName[ta]=பாம்DOC மாற்றி
+GenericName[tg]=Конвертёри PalmDOC
+GenericName[tr]=PalmDOC Çevirici
+GenericName[uk]=Перетворювач PalmDOC
+GenericName[zh_CN]=PalmDOC 转换器
+GenericName[zh_TW]=PalmDOC 轉換器
+Exec=kpalmdoc
+Icon=kpalmdoc
+Type=Application
+DocPath=kpalmdoc/index.html
+Terminal=false
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Unique
+Categories=Qt;KDE;Utility;X-KDE-Utilities-File;Office;PDA;
diff --git a/kpilot/conduits/docconduit/kpalmdoc.kcfg b/kpilot/conduits/docconduit/kpalmdoc.kcfg
new file mode 100644
index 000000000..4d3d22119
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc.kcfg
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0
+ http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" >
+ <kcfgfile name="converterrc"/>
+ <group name="General">
+ <entry name="TXTFolder" key="TXT folder" type="Path"/>
+ <entry name="PDBFolder" key="PDB folder" type="Path"/>
+ <entry name="SyncFolders" key="Sync folders" type="Bool">
+ <default>false</default>
+ </entry>
+ <entry name="AskOverwrite" key="Ask before overwriting files" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="VerboseMessages" key="Verbose messages" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="Compress" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="ConvertBookmarks" key="Convert bookmarks" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="BookmarksInline" key="Bookmarks inline" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="BookmarksEndtags" key="Bookmarks endtags" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="BookmarksBmk" key="Bookmarks bmk" type="Bool">
+ <default>true</default>
+ </entry>
+ <entry name="BookmarksToPC" key="Bookmarks to PC" type="UInt">
+ <default>0</default>
+ </entry>
+ <entry name="Encoding" type="String">
+ <default>ISO8859-15</default>
+ </entry>
+ </group>
+</kcfg>
diff --git a/kpilot/conduits/docconduit/kpalmdoc.upd b/kpilot/conduits/docconduit/kpalmdoc.upd
new file mode 100644
index 000000000..77d3d1eeb
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc.upd
@@ -0,0 +1,6 @@
+Id=kdepim_3.3
+File=converterrc
+Group=<default>,General
+AllKeys
+
+
diff --git a/kpilot/conduits/docconduit/kpalmdocSettings.kcfgc b/kpilot/conduits/docconduit/kpalmdocSettings.kcfgc
new file mode 100644
index 000000000..6da45c5e2
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdocSettings.kcfgc
@@ -0,0 +1,7 @@
+File=kpalmdoc.kcfg
+ClassName=KPalmDocSettings
+Singleton=true
+ItemAccessors=true
+Mutators=true
+GlobalEnums=true
+SetUserTexts=true
diff --git a/kpilot/conduits/docconduit/kpalmdoc_dlg.cc b/kpilot/conduits/docconduit/kpalmdoc_dlg.cc
new file mode 100644
index 000000000..5bdacba8c
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc_dlg.cc
@@ -0,0 +1,529 @@
+/* kpalmdoc_dlg.cpp
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This is the main dialog of the KDE PalmDOC converter.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+#include "options.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <iostream>
+
+#include <qtabwidget.h>
+#include <qcheckbox.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qlabel.h>
+#include <qcombobox.h>
+
+#include <klocale.h>
+#include <kconfig.h>
+#include <kaboutapplication.h>
+#include <kapplication.h>
+#include <kurlrequester.h>
+#include <kmessagebox.h>
+#include <kcharsets.h>
+
+#include <pilotLocalDatabase.h>
+
+#include "kpalmdoc_dlg.h"
+#include "kpalmdoc_dlgbase.h"
+#include "DOC-converter.h"
+#include "kpalmdocSettings.h"
+
+
+ConverterDlg::ConverterDlg( QWidget *parent, const QString& caption)
+ : KDialogBase( parent, "converterdialog", false, caption, KDialogBase::Close|KDialogBase::Help|KDialogBase::User1,
+ KDialogBase::Close, true, i18n("&About"))
+{
+ QWidget *page = makeHBoxMainWidget();
+ dlg=new ConverterDlgBase(page);
+ QStringList l = KGlobal::charsets()->descriptiveEncodingNames();
+ for ( QStringList::Iterator it = l.begin(); it != l.end(); ++it)
+ {
+ dlg->fEncoding->insertItem(*it);
+ }
+
+ readSettings();
+
+ connect(dlg->fDirectories, SIGNAL(toggled(bool)),
+ this, SLOT(slotDirectories(bool)));
+ connect(dlg->fTextToPDB, SIGNAL(clicked()), this, SLOT(slotToPDB()));
+ connect(dlg->fPDBToText, SIGNAL(clicked()), this, SLOT(slotToText()));
+
+ resize(minimumSize());
+}
+
+ConverterDlg::~ConverterDlg()
+{
+ // no need to delete child widgets, Qt does it all for us
+}
+void ConverterDlg::writeSettings()
+{
+ // General page
+ KPalmDocSettings::setTXTFolder( dlg->fTXTDir->url() );
+ KPalmDocSettings::setPDBFolder( dlg->fPDBDir->url() );
+ KPalmDocSettings::setSyncFolders( dlg->fDirectories->isChecked() );
+ KPalmDocSettings::setAskOverwrite( dlg->fAskOverwrite->isChecked() );
+ KPalmDocSettings::setVerboseMessages( dlg->fVerbose->isChecked() );
+ KPalmDocSettings::setEncoding( dlg->fEncoding->currentText() );
+
+ // PC->Handheld page
+ KPalmDocSettings::setCompress( dlg->fCompress->isChecked() );
+ KPalmDocSettings::setConvertBookmarks( dlg->fConvertBookmarks->isChecked() );
+ KPalmDocSettings::setBookmarksInline( dlg->fBookmarksInline->isChecked() );
+ KPalmDocSettings::setBookmarksEndtags( dlg->fBookmarksEndtags->isChecked() );
+ KPalmDocSettings::setBookmarksBmk( dlg->fBookmarksBmk->isChecked() );
+
+ // Handheld->PC page
+ KPalmDocSettings::setBookmarksToPC( dlg->fPCBookmarks->id(dlg->fPCBookmarks->selected()) );
+
+ KPalmDocSettings::self()->writeConfig();
+}
+
+void ConverterDlg::readSettings()
+{
+ FUNCTIONSETUP;
+
+ KPalmDocSettings::self()->readConfig();
+
+ // General Page:
+ dlg->fTXTDir->setURL(KPalmDocSettings::tXTFolder());
+ dlg->fPDBDir->setURL(KPalmDocSettings::pDBFolder());
+ bool dir=KPalmDocSettings::syncFolders();
+ dlg->fDirectories->setChecked(dir);
+ slotDirectories(dir);
+ dlg->fAskOverwrite->setChecked( KPalmDocSettings::askOverwrite() );
+ dlg->fVerbose->setChecked( KPalmDocSettings::verboseMessages() );
+ QString encoding = KPalmDocSettings::encoding();
+#ifdef DEBUG
+ DEBUGKPILOT << fname << ": Encoding=" << encoding << endl;
+#endif
+ dlg->fEncoding->setCurrentText( KPalmDocSettings::encoding() );
+
+ // PC->Handheld page
+ dlg->fCompress->setChecked(KPalmDocSettings::compress() );
+ dlg->fConvertBookmarks->setChecked(KPalmDocSettings::convertBookmarks());
+ dlg->fBookmarksInline->setChecked(KPalmDocSettings::bookmarksInline());
+ dlg->fBookmarksEndtags->setChecked(KPalmDocSettings::bookmarksEndtags());
+ dlg->fBookmarksBmk->setChecked(KPalmDocSettings::bookmarksBmk());
+
+ // Handheld->PC page
+ dlg->fPCBookmarks->setButton(KPalmDocSettings::bookmarksToPC() );
+}
+
+void ConverterDlg::slotClose()
+{
+ writeSettings();
+ kapp->quit();
+ delete this;
+}
+
+void ConverterDlg::slotToText()
+{
+ FUNCTIONSETUP;
+ // First, get the settings from the controls and initialize
+ // the converter object
+ int bmks=dlg->fPCBookmarks->id(dlg->fPCBookmarks->selected());
+ DOCConverter conv;
+ switch(bmks) {
+ case 0: conv.setBookmarkTypes(DOCConverter::eBmkNone); break;
+ case 1: conv.setBookmarkTypes(DOCConverter::eBmkInline); break;
+ case 2: conv.setBookmarkTypes(DOCConverter::eBmkEndtags); break;
+ case 3: conv.setBookmarkTypes(DOCConverter::eBmkDefaultBmkFile); break;
+ default:
+ break;
+ }
+
+ askOverwrite=dlg->fAskOverwrite->isChecked();
+ verbose=dlg->fVerbose->isChecked();
+
+
+ bool dir=dlg->fDirectories->isChecked();
+ QString txturl=dlg->fTXTDir->url();
+ QString pdburl=dlg->fPDBDir->url();
+
+ QFileInfo txtinfo(txturl);
+ QFileInfo pdbinfo(pdburl);
+
+ if (dir)
+ {
+ if (pdbinfo.isFile())
+ {
+ int res=KMessageBox::questionYesNo(this,
+ i18n("<qt>You selected to sync folders, "
+ "but gave a filename instead (<em>%1</em>)."
+ "<br>Use folder <em>%2</em> instead?</qt>").arg(pdburl)
+ .arg(pdbinfo.dirPath(true)), QString::null, i18n("Use Folder"), KStdGuiItem::cancel());
+ if (res==KMessageBox::Yes)
+ {
+ pdburl=pdbinfo.dirPath(true);
+ pdbinfo.setFile(pdburl);
+ }
+ else return;
+ }
+
+ if (!pdbinfo.isDir())
+ {
+ // no directory, so error message and return
+ KMessageBox::sorry(this,
+ i18n("<qt>The folder <em>%1</em> for "
+ "the handheld database files is not a valid "
+ "folder.</qt>").arg(pdburl));
+ return;
+ }
+
+ if (!pdbinfo.exists())
+ {
+ KMessageBox::sorry(this,
+ i18n("<qt>The folder <em>%1</em> for "
+ "the handheld database files is not a "
+ "valid directory.</qt>").arg(pdburl));
+ return;
+ }
+
+
+ // Now check the to directory:
+ if (txtinfo.isFile())
+ {
+ int res=KMessageBox::questionYesNo(this,
+ i18n("<qt>You selected to sync folders, "
+ "but gave a filename instead (<em>%1</em>)."
+ "<br>Use folder <em>%2</em> instead?</qt>").arg(txturl)
+ .arg(txtinfo.dirPath(true)), QString::null, i18n("Use Folder"), KStdGuiItem::cancel());
+ if (res==KMessageBox::Yes) {
+ txturl=txtinfo.dirPath(true);
+ txtinfo.setFile(txturl);
+ }
+ else return;
+ }
+
+ // Now that we have a directory path, try to create it:
+ if (!txtinfo.isDir()) {
+ txtinfo.dir().mkdir(txturl, true);
+ }
+ if (!txtinfo.isDir()) {
+ KMessageBox::sorry(this,
+ i18n("<qt>The folder <em>%1</em> for "
+ "the text files could not be created.</qt>").arg(txturl));
+ return;
+ }
+
+
+ // Now that we have both directories, create the converter object
+ DEBUGKPILOT<<"Pdbinfo.dir="<<pdbinfo.dir().absPath()<<endl;
+ DEBUGKPILOT<<"txtinfo.dir="<<txtinfo.dir().absPath()<<endl;
+ QStringList pdbfiles(pdbinfo.dir().entryList(CSL1("*.pdb")));
+ QStringList converted_Files;
+
+ DEBUGKPILOT<<"Length of filename list: "<<pdbfiles.size()<<endl;
+ for ( QStringList::Iterator it = pdbfiles.begin(); it != pdbfiles.end(); ++it )
+ {
+ QString txtfile=QFileInfo(*it).baseName(true)+CSL1(".txt");
+ DEBUGKPILOT<<"pdbfile="<<*it<<", pdbdir="<<pdburl<<", txtfile="<<txtfile<<", txtdir="<<txturl<<endl;
+ if (convertPDBtoTXT(pdburl, *it, txturl, txtfile, &conv))
+ {
+ converted_Files.append(*it);
+ }
+ }
+ if (converted_Files.size()>0) {
+ KMessageBox::informationList(this, i18n("The following texts were "
+ "successfully converted:"), converted_Files, i18n("Conversion Successful"));
+ }
+ else
+ {
+ KMessageBox::sorry(this, i18n("No text files were converted correctly"));
+ }
+
+
+ } else { // no dir
+
+
+ // Check the from file
+ if (!pdbinfo.isFile() || !pdbinfo.exists())
+ {
+ KMessageBox::sorry(this, i18n("<qt>The file <em>%1</em> does not "
+ "exist.</qt>").arg(pdburl));
+ return;
+ }
+
+ // Now check the to file
+/* // I can't check if a given filename is a valid filename
+ if (!txtinfo.isFile())
+ {
+ KMessageBox::sorry(this, i18n("<qt>The filename <em>%1</em> for the "
+ "text is not a valid filename.</qt>").arg(txturl));
+ return;
+ }*/
+ if (convertPDBtoTXT(pdbinfo.dirPath(true), pdbinfo.fileName(),
+ txtinfo.dirPath(true), txtinfo.fileName(), &conv) )
+ {
+ KMessageBox::information(this, i18n("Conversion of file %1 successful.").arg(pdburl));
+ }
+
+ }
+
+}
+
+void ConverterDlg::slotToPDB()
+{
+ FUNCTIONSETUP;
+ // First, get the settings from the controls and initialize
+ // the converter object
+ bool compress=dlg->fCompress->isChecked();
+ int bmks=0;
+ if (dlg->fConvertBookmarks->isChecked())
+ {
+ if (dlg->fBookmarksInline->isChecked()) bmks|=DOCConverter::eBmkInline;
+ if (dlg->fBookmarksEndtags->isChecked()) bmks|=DOCConverter::eBmkEndtags;
+ if(dlg->fBookmarksBmk->isChecked()) bmks|=DOCConverter::eBmkDefaultBmkFile;
+ }
+ DOCConverter conv;
+ conv.setBookmarkTypes(bmks);
+ conv.setCompress(compress);
+ conv.setSort(DOCConverter::eSortName);
+
+
+ askOverwrite=dlg->fAskOverwrite->isChecked();
+ verbose=dlg->fVerbose->isChecked();
+
+
+ bool dir=dlg->fDirectories->isChecked();
+ QString txturl=dlg->fTXTDir->url();
+ QString pdburl=dlg->fPDBDir->url();
+
+ QFileInfo txtinfo(txturl);
+ QFileInfo pdbinfo(pdburl);
+
+ if (dir)
+ {
+ if (txtinfo.isFile())
+ {
+ int res=KMessageBox::questionYesNo(this,
+ i18n("<qt>You selected to sync folders, "
+ "but gave a filename instead (<em>%1</em>)."
+ "<br>Use folder <em>%2</em> instead?</qt>").arg(txturl)
+ .arg(txtinfo.dirPath(true)), QString::null, i18n("Use Folder"), KStdGuiItem::cancel());
+ if (res==KMessageBox::Yes)
+ {
+ txturl=txtinfo.dirPath(true);
+ txtinfo.setFile(txturl);
+ }
+ else return;
+ }
+
+ if (!txtinfo.isDir() || !txtinfo.exists())
+ {
+ KMessageBox::sorry(this,
+ i18n("<qt>The folder <em>%1</em> for "
+ "the text files is not a valid folder.</qt>").arg(txturl));
+ return;
+ }
+
+
+ // Now check the to directory:
+ if (pdbinfo.isFile())
+ {
+ int res=KMessageBox::questionYesNo(this,
+ i18n("<qt>You selected to sync folders, "
+ "but gave a filename instead (<em>%1</em>)."
+ "<br>Use folder <em>%2</em> instead?</qt>")
+ .arg(pdburl)
+ .arg(pdbinfo.dirPath(true)), QString::null, i18n("Use Folder"), KStdGuiItem::cancel());
+ if (res==KMessageBox::Yes) {
+ pdburl=pdbinfo.dirPath(true);
+ pdbinfo.setFile(pdburl);
+ }
+ else return;
+ }
+
+ // Now that we have a directory path, try to create it:
+ if (!pdbinfo.isDir()) {
+ pdbinfo.dir().mkdir(pdburl, true);
+ }
+ if (!pdbinfo.isDir()) {
+ KMessageBox::sorry(this, i18n("<qt>The folder <em>%1</em> for "
+ "the PalmDOC files could not be created.</qt>").arg(pdburl));
+ return;
+ }
+
+
+ // Now that we have both directories, create the converter object
+ DEBUGKPILOT<<"Pdbinfo.dir="<<pdbinfo.dir().absPath()<<endl;
+ DEBUGKPILOT<<"txtinfo.dir="<<txtinfo.dir().absPath()<<endl;
+ QStringList txtfiles(txtinfo.dir().entryList(CSL1("*.txt")));
+ QStringList converted_Files;
+
+ DEBUGKPILOT<<"Length of filename list: "<<txtfiles.size()<<endl;
+ for ( QStringList::Iterator it = txtfiles.begin(); it != txtfiles.end(); ++it )
+ {
+ QString pdbfile=QFileInfo(*it).baseName(true)+CSL1(".pdb");
+ DEBUGKPILOT<<"pdbfile="<<pdbfile<<", pdbdir="<<pdburl<<", txtfile="<<*it<<", txtdir="<<txturl<<endl;
+ if (convertTXTtoPDB(txturl, *it, pdburl, pdbfile, &conv))
+ {
+ converted_Files.append(*it);
+ }
+ }
+ if (converted_Files.size()>0) {
+ KMessageBox::informationList(this, i18n("The following texts were "
+ "successfully converted:"), converted_Files, i18n("Conversion Successful"));
+ }
+ else
+ {
+ KMessageBox::sorry(this, i18n("No text files were converted correctly"));
+ }
+
+
+ } else { // no dir
+
+
+ // Check the from file
+ if (!txtinfo.isFile() || !txtinfo.exists())
+ {
+ KMessageBox::sorry(this, i18n("<qt>The file <em>%1</em> does not "
+ "exist.</qt>").arg(txturl));
+ return;
+ }
+
+ if (convertTXTtoPDB(txtinfo.dirPath(true), txtinfo.fileName(),
+ pdbinfo.dirPath(true), pdbinfo.fileName(), &conv) )
+ {
+ KMessageBox::information(this, i18n("Conversion of file %1 successful.").arg(txturl));
+ }
+
+ }
+
+}
+
+
+void ConverterDlg::slotUser1()
+{
+ KAboutApplication ab(KGlobal::instance()->aboutData(), this);
+ ab.show();
+ ab.exec();
+ return;
+}
+
+void ConverterDlg::slotDirectories(bool dir)
+{
+ FUNCTIONSETUP;
+ DEBUGKPILOT<<"Slot Directories: "<<dir<<endl;
+ if (dir)
+ {
+ dlg->fTextLabel->setText(i18n("&Text folder:"));
+ dlg->fPdbLabel->setText(i18n("&PalmDOC folder:"));
+ dlg->fTXTDir->setMode(KFile::LocalOnly | KFile::Directory);
+ dlg->fPDBDir->setMode(KFile::LocalOnly | KFile::Directory);
+ } else {
+ dlg->fTextLabel->setText(i18n("&Text file:"));
+ dlg->fPdbLabel->setText(i18n("&DOC file:"));
+ dlg->fTXTDir->setMode(KFile::LocalOnly | KFile::File);
+ dlg->fPDBDir->setMode(KFile::LocalOnly | KFile::File);
+ }
+}
+
+bool ConverterDlg::convertTXTtoPDB(QString txtdir, QString txtfile,
+ QString pdbdir, QString pdbfile, DOCConverter*conv)
+{
+ FUNCTIONSETUP;
+ bool res=false;
+ QFileInfo dbfileinfo(pdbdir, pdbfile);
+ DEBUGKPILOT<<"Working on file "<<pdbfile<<endl;
+ if (!dbfileinfo.exists() || !askOverwrite ||
+ (KMessageBox::Yes==KMessageBox::questionYesNo(this,
+ i18n("<qt>The database file <em>%1</em> already exists. Overwrite it?</qt>")
+ .arg(dbfileinfo.filePath()), QString::null, i18n("Overwrite"), KStdGuiItem::cancel() ) ))
+ {
+ PilotLocalDatabase*pdbdb=new PilotLocalDatabase(pdbdir, QFileInfo(pdbfile).baseName(), false);
+ if (pdbdb)
+ {
+ if (!pdbdb->isOpen())
+ {
+#ifdef DEBUG
+ DEBUGKPILOT<<pdbfile<<" does not yet exist. Creating it"<<endl;
+#endif
+ if (!pdbdb->createDatabase(get_long("REAd"), get_long("TEXt")) ) {
+ }
+ }
+
+ if (pdbdb->isOpen())
+ {
+ conv->setPDB(pdbdb);
+ conv->setTXTpath(txtdir, txtfile);
+ DEBUGKPILOT<<"Converting "<<txtfile<<" (dir "<<txtdir<<") to "<<dbfileinfo.filePath()<<endl;
+ if (conv->convertTXTtoPDB()) res=true;
+ }
+ delete pdbdb;
+ }
+ if ( !res && verbose )
+ {
+ KMessageBox::sorry(this, i18n("<qt>Error while converting the text %1.</qt>").arg(txtfile));
+ }
+ }
+ else
+ {
+ DEBUGKPILOT<<"Ignoring the file "<<txtfile<<endl;
+ }
+ return res;
+}
+
+bool ConverterDlg::convertPDBtoTXT(QString pdbdir, QString pdbfile,
+ QString txtdir, QString txtfile, DOCConverter*conv)
+{
+ FUNCTIONSETUP;
+ bool res=false;
+ QFileInfo txtfileinfo(txtdir, txtfile);
+ DEBUGKPILOT<<"Working on file "<<txtfile<<endl;
+ if (!txtfileinfo.exists() || !askOverwrite ||
+ (KMessageBox::Yes==KMessageBox::questionYesNo(this,
+ i18n("<qt>The text file <em>%1</em> already exists. Overwrite it?</qt>")
+ .arg(txtfileinfo.filePath()), QString::null, i18n("Overwrite"), KStdGuiItem::cancel() ) ))
+ {
+ PilotLocalDatabase*pdbdb=new PilotLocalDatabase(pdbdir, QFileInfo(pdbfile).baseName(), false);
+ if (pdbdb)
+ {
+ if (pdbdb->isOpen())
+ {
+ conv->setPDB(pdbdb);
+ conv->setTXTpath(txtdir, txtfile);
+ DEBUGKPILOT<<"Converting "<<txtfile<<" (dir "<<txtdir<<") from "<<pdbfile<<" (dir "<<pdbdir<<")"<<endl;
+ if (conv->convertPDBtoTXT()) res=true;
+ }
+ delete pdbdb;
+ }
+ if ( !res && verbose )
+ {
+ KMessageBox::sorry(this, i18n("<qt>Error while converting the text %1.</qt>").arg(pdbfile));
+ }
+ }
+ else
+ {
+ DEBUGKPILOT<<"Ignoring the file "<<pdbfile<<endl;
+ }
+ return res;
+
+}
+
+#include "kpalmdoc_dlg.moc"
diff --git a/kpilot/conduits/docconduit/kpalmdoc_dlg.h b/kpilot/conduits/docconduit/kpalmdoc_dlg.h
new file mode 100644
index 000000000..410b24568
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc_dlg.h
@@ -0,0 +1,67 @@
+/* kpalmdoc_dlg.cpp
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This is the main dialog of the KDE PalmDOC converter.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+#ifndef CONVERTERDLG_H
+#define CONVERTERDLG_H
+
+#include <kdialogbase.h>
+class ConverterDlgBase;
+class DOCConverter;
+
+class ConverterDlg : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ ConverterDlg( QWidget *parent=0, const QString& caption=0);
+ ~ConverterDlg();
+
+protected slots:
+ virtual void slotClose();
+ void slotToText();
+ void slotToPDB();
+ void slotDirectories(bool dir);
+ void slotUser1();
+protected:
+ void writeSettings();
+ void readSettings();
+
+ // These two functions convert one single file to or from a pdb database
+ bool convertTXTtoPDB(QString txtdir, QString txtfile,
+ QString pdbdir, QString pdbfile, DOCConverter*conv);
+ bool convertPDBtoTXT(QString pdbdir, QString pdbfile,
+ QString txtdir, QString txtfile, DOCConverter*conv);
+
+
+ // The actual dialog widget (designer created) holding all controls
+ ConverterDlgBase*dlg;
+ // Settings
+ bool askOverwrite;
+ bool verbose;
+};
+
+#endif // CONVERTERDLG_H
diff --git a/kpilot/conduits/docconduit/kpalmdoc_dlgbase.ui b/kpilot/conduits/docconduit/kpalmdoc_dlgbase.ui
new file mode 100644
index 000000000..8b3e89668
--- /dev/null
+++ b/kpilot/conduits/docconduit/kpalmdoc_dlgbase.ui
@@ -0,0 +1,435 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>ConverterDlgBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>ConverterDlgBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>492</width>
+ <height>339</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTabWidget" row="0" column="0">
+ <property name="name">
+ <cstring>tabWidget</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>General</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>fPdbLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;PalmDOC file:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fPDBDir</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>fTextLabel</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Text file:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fTXTDir</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="2" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fDirectories</cstring>
+ </property>
+ <property name="text">
+ <string>Convert whole &amp;folders</string>
+ </property>
+ </widget>
+ <widget class="KURLRequester" row="1" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fPDBDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Folder where copies of the handheld databases are kept. You can install them to any PalmOS handheld, and distribute these copies to other people (but beware of copyright infringement).</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fAskOverwrite</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Ask before overwriting files</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="4" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fVerbose</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Verbose messages</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="7" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fTextToPDB</cstring>
+ </property>
+ <property name="text">
+ <string>Convert Text to PalmDOC</string>
+ </property>
+ </widget>
+ <widget class="KPushButton" row="7" column="2">
+ <property name="name">
+ <cstring>fPDBToText</cstring>
+ </property>
+ <property name="text">
+ <string>Convert PalmDOC to Text</string>
+ </property>
+ </widget>
+ <spacer row="6" column="1">
+ <property name="name">
+ <cstring>spacer5</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KURLRequester" row="0" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fTXTDir</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Enter the name of the folder where the text files reside on the PC. All files with extension .txt will be synced to the handheld.</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="5" column="1" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fEncoding</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Encoding:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fEncoding</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>PC -&gt; Handheld</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="3" column="0">
+ <property name="name">
+ <cstring>spacer6</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="4" column="0">
+ <property name="name">
+ <cstring>spacer7</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer8</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QCheckBox" row="2" column="1">
+ <property name="name">
+ <cstring>fBookmarksInline</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Inline tags in text</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>When a &lt;* bookmarktext *&gt; appears somewhere in the text, a bookmark will be set at this position, and the text between the &lt;* and the *&gt; will be used as bookmark name. The &lt;*...*&gt; will be removed from the text.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="3" column="1">
+ <property name="name">
+ <cstring>fBookmarksEndtags</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Tags at end of text</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Tags of the form &lt;bookmarkname&gt; at the end of the text will be used to search the text for the pattern between the &lt; and &gt;. Whenever "bookmarkname" appears in the text, a bookmark will be set there. The endtags &lt;...&gt; will then be removed from the end of the text.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fCompress</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Compress</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Check this box, if the text should be compressed on the handheld to save memory. Most doc reader on the handheld support compressed texts.</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The Palm doc format supports compressing the text to save memory. If you check this box, the text will consume about 50% less memory than in uncompressed state. Almost all DOC readers on the Palm support compressed texts.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>fConvertBookmarks</cstring>
+ </property>
+ <property name="text">
+ <string>Convert &amp;bookmarks</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Do you want to convert bookmarks? Most doc readers support bookmarks. You have to provide some information about where the bookmarks should be set and their titles. Check at least one of the bookmark types below.</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="4" column="1">
+ <property name="name">
+ <cstring>fBookmarksBmk</cstring>
+ </property>
+ <property name="text">
+ <string>Regular &amp;expressions in .bmk file</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Use regular expressions in a file textname.bmk (textname.txt is the filename of the text) to search the text for bookmarks.See the documentation for a description of the format of the bmk file.</string>
+ </property>
+ </widget>
+ <spacer row="5" column="1">
+ <property name="name">
+ <cstring>spacer9</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>200</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Handheld -&gt; PC</string>
+ </attribute>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer10</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>21</width>
+ <height>190</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>fPCBookmarks</cstring>
+ </property>
+ <property name="title">
+ <string>Convert Bookmarks</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QRadioButton" row="1" column="0">
+ <property name="name">
+ <cstring>radioButton9</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Convert as &amp;inline tags</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>1</number>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="0" column="0">
+ <property name="name">
+ <cstring>radioButton8</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Do &amp;not convert bookmarks</string>
+ </property>
+ <property name="buttonGroupId">
+ <number>0</number>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="2" column="0">
+ <property name="name">
+ <cstring>radioButton10</cstring>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>Convert as &amp;end tags</string>
+ </property>
+ </widget>
+ <widget class="QRadioButton" row="3" column="0">
+ <property name="name">
+ <cstring>radioButton11</cstring>
+ </property>
+ <property name="text">
+ <string>Convert into .bmk &amp;file</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ </grid>
+ </widget>
+ </widget>
+ </grid>
+</widget>
+<customwidgets>
+</customwidgets>
+<connections>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksInline</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksEndtags</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>fConvertBookmarks</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fBookmarksBmk</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+</connections>
+<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>
diff --git a/kpilot/conduits/docconduit/makedoc9.cc b/kpilot/conduits/docconduit/makedoc9.cc
new file mode 100644
index 000000000..1f1c56ff1
--- /dev/null
+++ b/kpilot/conduits/docconduit/makedoc9.cc
@@ -0,0 +1,405 @@
+// based on: MakeDoc, version 2
+// I only took the tBuf class from there and adapted it.
+//
+// Compresses text files into a format that is ready to export to a Pilot
+// and work with Rick Bram's PilotDOC reader.
+// Copyright (C) Reinhold Kainhofer, 2002
+// Copyrigth (C) Pat Beirne, 2000
+//
+// Original file (makedoc9.cpp) copyright by:
+// Copyright (C) Pat Beirne, 2000.
+// Distributable under the GNU General Public License Version 2 or later.
+//
+// ver 0.6 enforce 31 char limit on database names
+// ver 0.7 change header and record0 to structs
+// ver 2.0 added category control on the command line
+// changed extensions from .prc to .pdb
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <iostream>
+
+
+#include "makedoc9.h"
+
+
+
+//
+// Issue()
+//
+// action: handle the details of writing a single
+// character to the compressed stream
+//
+unsigned
+ tBuf::Issue(byte src, int &bSpace)
+{
+ unsigned int iDest = len;
+ byte *dest = buf;
+
+ // TODO: which of the if parts should really be included???
+#if 0
+ // modified version of issue
+ // just issue the char
+ if (src >= 0x80 || src <= 8)
+ dest[iDest++] = 1;
+ dest[iDest++] = src;
+
+#else
+ // if there is an outstanding space char, see if
+ // we can squeeze it in with an ASCII char
+ if (bSpace)
+ {
+ if (src >= 0x40 && src <= 0x7F)
+ dest[iDest++] = src ^ 0x80;
+ else
+ {
+ // couldn't squeeze it in, so issue the space char by itself
+ // most chars go out simple, except the range 1...8,0x80...0xFF
+ dest[iDest++] = ' ';
+ if (src < 0x80 && (src == 0 || src > 8))
+ dest[iDest++] = src;
+ else
+ dest[iDest++] = 1, dest[iDest++] = src;
+ }
+ // knock down the space flag
+ bSpace = 0;
+ }
+ else
+ {
+ // check for a space char
+ if (src == ' ')
+ bSpace = 1;
+ else
+ {
+ if (src < 0x80 && (src == 0 || src > 8))
+ dest[iDest++] = src;
+ else
+ dest[iDest++] = 1, dest[iDest++] = src;
+
+ }
+ }
+#endif
+ len = iDest;
+ return iDest;
+}
+
+//
+// Compress
+//
+// params: none
+//
+// action: takes the given buffer,
+// and compresses
+// the original data down into a second buffer
+//
+// comment: This version make heavy use of walking pointers.
+//
+unsigned tBuf::Compress()
+{
+ if (!buf)
+ return 0;
+ if (isCompressed) {
+// cout<<"Buffer is already compressed!"<<endl;
+ return len;
+// } else {
+// cout<<" Compressing buffer!!!"<<endl;
+ }
+
+ unsigned int i;
+
+ // run through the input buffer
+ byte *pBuffer; // points to the input buffer
+ byte *pHit; // points to a walking test hit; works upwards on successive matches
+ byte *pPrevHit; // previous value of pHit; also, start of next test
+ byte *pTestHead; // current test string
+ byte *pTestTail; // current walking pointer; one past the current test buffer
+ byte *pEnd; // 1 past the end of the input buffer
+
+ pHit = pPrevHit = pTestHead = pBuffer = buf;
+ pTestTail = pTestHead + 1;
+ pEnd = buf + len; // should point to a 0!
+
+ // make a dest buffer and reassign the local buffer
+ buf = new byte[6000];
+ len = 0; // used to walk through the output buffer
+
+ // loop, absorbing one more char from the input buffer on each pass
+ for (; pTestHead != pEnd; pTestTail++)
+ {
+ // if we already have 10 char match, don't bother scanning again for the 11th (wasted time)
+ if (pTestTail - pTestHead != (1 << COUNT_BITS) + 3)
+ {
+ // scan in the previous data for a match
+ // terminate the test string (and the matcher string, as well!) in a 0
+ byte tmp = *pTestTail;
+
+ *pTestTail = 0;
+ pHit = (byte *) strstr((const char *) pPrevHit,
+ (const char *) pTestHead);
+ *pTestTail = tmp; // restore the char
+ }
+
+ // on a mismatch or end of buffer, issued codes
+ if (pHit == pTestHead
+ || pTestTail - pTestHead > (1 << COUNT_BITS) + 2
+ || pTestTail == pEnd)
+ {
+ // issue the codes
+ // first, check for short runs
+ if (pTestTail - pTestHead < 4)
+ {
+ if (pTestHead[0] > 0x7F || pTestHead[0] <= 8)
+ buf[len++] = 1;
+ buf[len++] = pTestHead[0];
+ pTestHead++;
+ }
+ // for longer runs, issue a run-code
+ else
+ {
+ unsigned int dist = pTestHead - pPrevHit;
+ unsigned int compound =
+ (dist << COUNT_BITS) + pTestTail - pTestHead - 4;
+
+//if (dist>=(1<<DISP_BITS)) printf("\n!! error dist overflow");
+//if (pTestTail-pTestHead-4>7) printf("\n!! error len overflow");
+
+ buf[len++] = 0x80 + (compound >> 8);
+ buf[len++] = compound & 0xFF;
+//printf("\nissuing code for sequence len %d <%c%c%c>",pTestTail-pTestHead-1,pTestHead[0],pTestHead[1],pTestHead[2]);
+//printf("\n <%x%x>",pOut[-2],pOut[-1]);
+ // and start again
+ pTestHead = pTestTail - 1;
+ }
+ // start the search again
+ pPrevHit = pBuffer;
+ // within range
+ if (pTestHead - pPrevHit > ((1 << DISP_BITS) - 1))
+ pPrevHit = pTestHead - ((1 << DISP_BITS) - 1);
+ }
+ // got a match
+ else
+ {
+ pPrevHit = pHit;
+ }
+ // when we get to the end of the buffer, don't inc past the end
+ // this forces the residue chars out one at a time
+ if (pTestTail == pEnd)
+ pTestTail--;
+ }
+
+
+ // final scan to merge consecutive high chars together
+ // and merge space chars
+ unsigned int k;
+
+ for (i = k = 0; i < len; i++, k++)
+ {
+ buf[k] = buf[i];
+ // skip the run-length codes
+ if (buf[k] >= 0x80 && buf[k] < 0xC0)
+ buf[++k] = buf[++i];
+ // if we hit a high char marker, look ahead for another
+ // and merge multiples together
+ else if (buf[k] == 1)
+ {
+ buf[k + 1] = buf[i + 1];
+ while (i + 2 < len && buf[i + 2] == 1 && buf[k] < 8)
+ {
+ buf[k]++;
+ buf[k + buf[k]] = buf[i + 3];
+ i += 2;
+ }
+ k += buf[k];
+ i++;
+ }
+ else if (buf[k] == ' ' && i < len - 1 && buf[i + 1] <= 0x7F
+ && buf[i + 1] >= 0x40)
+ buf[k] = 0x80 | buf[++i];
+ }
+
+ // delete original buffer
+ delete[]pBuffer;
+ len = k;
+
+ isCompressed = true;
+ return k;
+}
+
+/*
+ Decompress
+
+ params: none
+
+ action: make a new buffer
+ run through the source data
+ check the 4 cases:
+ 0,9...7F represent self
+ 1...8 escape n chars
+ 80...bf reference earlier run
+ c0...ff space+ASCII
+
+*/
+unsigned tBuf::Decompress()
+{
+ if (!buf)
+ return 0;
+ if (!isCompressed) {
+// cout<<"Buffer already uncompressed. Doing nothing"<<endl;
+ return len;
+// } else {
+// cout<<"Decompressing buffer"<<endl;
+ }
+
+ // we "know" that all decompresses fit within 4096, right?
+ byte *pOut = new byte[6000];
+ byte *in_buf = buf;
+ byte *out_buf = pOut;
+
+ unsigned int i, j;
+
+ for (j = i = 0; j < len;)
+ {
+ unsigned int c;
+
+ // take a char from the input buffer
+ c = in_buf[j++];
+
+ // separate the char into zones: 0, 1...8, 9...0x7F, 0x80...0xBF, 0xC0...0xFF
+
+ // codes 1...8 mean copy that many bytes; for accented chars & binary
+ if (c > 0 && c < 9)
+ while (c--)
+ out_buf[i++] = in_buf[j++];
+
+ // codes 0, 9...0x7F represent themselves
+ else if (c < 0x80)
+ out_buf[i++] = c;
+
+ // codes 0xC0...0xFF represent "space + ascii char"
+ else if (c >= 0xC0)
+ out_buf[i++] = ' ', out_buf[i++] = c ^ 0x80;
+
+ // codes 0x80...0xBf represent sequences
+ else
+ {
+ int m, n;
+
+ c <<= 8;
+ c += in_buf[j++];
+ m = (c & 0x3FFF) >> COUNT_BITS;
+ n = c & ((1 << COUNT_BITS) - 1);
+ n += 3;
+ while (n--)
+ {
+ out_buf[i] = out_buf[i - m];
+ i++;
+ }
+ }
+ }
+ out_buf[i++]='\0';
+ out_buf[i++]='\0';
+ delete[]buf;
+ buf = pOut;
+ len = i;
+
+ isCompressed = false;
+ return i;
+}
+
+unsigned tBuf::DuplicateCR()
+{
+ if (!buf)
+ return 0;
+ byte *pBuf = new byte[2 * len];
+
+ unsigned int k, j;
+
+ for (j = k = 0; j < len; j++, k++)
+ {
+ pBuf[k] = buf[j];
+ if (pBuf[k] == 0x0A)
+ pBuf[k++] = 0x0D, pBuf[k] = 0x0A;
+ }
+ delete[]buf;
+ buf = pBuf;
+ len = k;
+ return k;
+}
+
+
+
+// this nasty little beast removes really low ASCII and 0's
+// and handles the CR problem
+//
+// if a cr appears before a lf, then remove the cr
+// if a cr appears in isolation, change to a lf
+unsigned tBuf::RemoveBinary()
+{
+ if (!buf)
+ return 0;
+ byte *in_buf = buf;
+ byte *out_buf = new byte[len];
+
+ unsigned int k, j;
+
+ for (j = k = 0; j < len; j++, k++)
+ {
+ // copy each byte
+ out_buf[k] = in_buf[j];
+
+ // throw away really low ASCII
+ if (( /*out_buf[k]>=0 && */ out_buf[k] < 9))
+ k--;
+
+ // for CR
+ if (out_buf[k] == 0x0D)
+ {
+ // if next is LF, then drop it
+ if (j < len - 1 && in_buf[j + 1] == 0x0A)
+ k--;
+ else // turn it into a LF
+ out_buf[k] = 0x0A;
+ }
+ }
+ delete[]buf;
+ buf = out_buf;
+ len = k;
+ return k;
+}
+
+void tBuf::setText(const byte * text, unsigned txtlen, bool txtcomp)
+{
+ if (buf)
+ delete[]buf;
+ buf = 0L;
+
+ if (txtlen <= 0)
+ txtlen = strlen((const char *) text);
+ len = txtlen;
+ buf = new byte[len];
+
+ memcpy(buf, text, len*sizeof(char));
+// strncpy((char *) buf, (const char *) text, len);
+ isCompressed = txtcomp;
+// cout<<"Setting text, compressed="<<txtcomp<<endl;
+}
diff --git a/kpilot/conduits/docconduit/makedoc9.h b/kpilot/conduits/docconduit/makedoc9.h
new file mode 100644
index 000000000..27e3695d4
--- /dev/null
+++ b/kpilot/conduits/docconduit/makedoc9.h
@@ -0,0 +1,111 @@
+#ifndef MAKEDOC_H
+#define MAKEDOC_H
+// based on: MakeDoc, version 2
+// I only took the tBuf class from there and adapted it.
+//
+// Compresses text files into a format that is ready to export to a Pilot
+// and work with Rick Bram's PilotDOC reader.
+// Copyright (C) Reinhold Kainhofer, 2002
+// Copyrigth (C) Pat Beirne, 2000
+//
+// Original file (makedoc9.cpp) copyright by:
+// Copyright (C) Pat Beirne, 2000.
+// Distributable under the GNU General Public License Version 2 or later.
+//
+// ver 0.6 enforce 31 char limit on database names
+// ver 0.7 change header and record0 to structs
+// ver 2.0 added category control on the command line
+// changed extensions from .prc to .pdb
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+#include <stdio.h>
+
+typedef unsigned char byte;
+typedef unsigned long DWORD;
+typedef unsigned short WORD;
+
+#define DISP_BITS 11
+#define COUNT_BITS 3
+
+
+
+
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+///////////////////// //////////////////////
+///////////////////// tBuf class //////////////////////
+///////////////////// //////////////////////
+/////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+
+class tBuf {
+ private:
+// byte hichar[10];
+// int hicharnum;
+// bool space;
+
+ byte * buf;
+ unsigned len;
+ bool isCompressed;
+ public:
+ tBuf() {
+ buf = 0L;
+ len=0;
+ isCompressed=false;
+ };
+
+ ~tBuf()
+ {
+ if (buf)
+ delete[]buf;
+ }
+
+ void Clear() {
+ delete[]buf;
+ buf = 0L;
+ }
+ void setText(const byte * text, unsigned int txtlen =
+ 0, bool txtcomp = false);
+ byte *text() const {
+ return buf;
+ }
+ unsigned Len() const {
+ return len;
+ }
+ void setCompressed(bool compressed = true) {
+ isCompressed = compressed;
+ }
+ bool compressed() const {
+ return isCompressed;
+ }
+ unsigned RemoveBinary();
+ unsigned DuplicateCR();
+
+ unsigned Decompress();
+ unsigned Compress();
+
+ private:
+ unsigned Issue(byte src, int &bSpace);
+ void Dump() const {
+ printf("\nbuffer len=%d", len);
+}};
+
+
+#endif
diff --git a/kpilot/conduits/docconduit/pilotDOCBookmark.cc b/kpilot/conduits/docconduit/pilotDOCBookmark.cc
new file mode 100644
index 000000000..9b93f2af1
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCBookmark.cc
@@ -0,0 +1,87 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This is a C++ class for the DOC bookmark record structure
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+#include "options.h"
+#include "pilotDOCBookmark.h"
+
+
+
+PilotDOCBookmark::PilotDOCBookmark():PilotRecordBase(), pos(0)
+{
+ FUNCTIONSETUP;
+ memset(&bookmarkName[0], 0, 16);
+}
+
+
+
+/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDOCBookmark()
+*/
+PilotDOCBookmark::PilotDOCBookmark(PilotRecord * rec):PilotRecordBase(rec)
+{
+ if (rec)
+ {
+ const pi_buffer_t *b = rec->buffer();
+ unsigned int offset = 0;
+ Pilot::dlp<char *>::read(b,offset,bookmarkName,16);
+ bookmarkName[16]='\0';
+ pos = Pilot::dlp<long>::read(b,offset);
+ }
+}
+
+
+
+PilotDOCBookmark::PilotDOCBookmark(const PilotDOCBookmark & e):PilotRecordBase(e)
+{
+ FUNCTIONSETUP;
+ *this = e;
+}
+
+
+
+PilotDOCBookmark & PilotDOCBookmark::operator =(const PilotDOCBookmark & e)
+{
+ if (this != &e)
+ {
+ strncpy(&bookmarkName[0], &e.bookmarkName[0], 16);
+ bookmarkName[16]='\0';
+ pos = e.pos;
+ }
+ return *this;
+}
+
+
+
+PilotRecord *PilotDOCBookmark::pack() const
+{
+ pi_buffer_t *b = pi_buffer_new( 16 + Pilot::dlp<long>::size );
+ pi_buffer_append(b, bookmarkName, 16);
+ b->data[16] = 0;
+ Pilot::dlp<long>::append(b,pos);
+ PilotRecord* rec = new PilotRecord(b, this);
+ return rec;
+}
diff --git a/kpilot/conduits/docconduit/pilotDOCBookmark.h b/kpilot/conduits/docconduit/pilotDOCBookmark.h
new file mode 100644
index 000000000..fe511fc17
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCBookmark.h
@@ -0,0 +1,51 @@
+/* pilotDOCBookmark.h -*- C++ -*- KPilot
+**
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** See the .cc file for an explanation of what this file is for.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+#ifndef _KPILOT_PILOTDOCBOOKMARK_H
+#define _KPILOT_PILOTDOCBOOKMARK_H
+
+#include <pilotRecord.h>
+class PilotRecord;
+
+
+class PilotDOCBookmark:public PilotRecordBase {
+public:
+ PilotDOCBookmark();
+ PilotDOCBookmark(PilotRecord * rec);
+ PilotDOCBookmark(const PilotDOCBookmark & e);
+ ~PilotDOCBookmark() {};
+ PilotDOCBookmark & operator=(const PilotDOCBookmark & e);
+
+ PilotRecord *pack() const;
+
+public:
+ char bookmarkName[17];
+ long int pos;
+};
+
+
+#endif
diff --git a/kpilot/conduits/docconduit/pilotDOCEntry.cc b/kpilot/conduits/docconduit/pilotDOCEntry.cc
new file mode 100644
index 000000000..75a51cefa
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCEntry.cc
@@ -0,0 +1,92 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This is a C++ class dealing with PalmDOC text records
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+
+#include "options.h"
+#include "pilotDOCEntry.h"
+
+
+
+const int PilotDOCEntry::TEXT_SIZE = 4096;
+
+
+PilotDOCEntry::PilotDOCEntry():PilotRecordBase()
+{
+ FUNCTIONSETUP;
+ compress = false;
+}
+
+
+
+/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDOCEntry()
+*/
+PilotDOCEntry::PilotDOCEntry(PilotRecord * rec, bool compressed):PilotRecordBase(rec)
+{
+ if (rec) fText.setText((unsigned char *) rec->data(), rec->size(), compressed);
+ compress = compressed;
+}
+
+
+
+PilotDOCEntry::PilotDOCEntry(const PilotDOCEntry & e):PilotRecordBase(e)
+{
+ FUNCTIONSETUP;
+ // See PilotDateEntry::operator = for details
+ fText.setText(e.fText.text(), e.fText.Len(), e.fText.compressed());
+ compress = e.compress;
+}
+
+
+
+PilotDOCEntry & PilotDOCEntry::operator =(const PilotDOCEntry & e)
+{
+ if (this != &e)
+ {
+ fText.setText(e.fText.text(), e.fText.Len(), e.fText.compressed());
+ compress = e.compress;
+ }
+ return *this;
+}
+
+
+
+
+PilotRecord *PilotDOCEntry::pack()
+{
+ int len = compress ? fText.Compress() : fText.Decompress();
+
+ if (len<0)
+ {
+ return 0L;
+ }
+
+ pi_buffer_t *b = pi_buffer_new( len + 4 ); // +4 for safety
+ memcpy( b->data, (const char *) fText.text(), len );
+ b->used = len;
+ PilotRecord* rec = new PilotRecord(b, this);
+ return rec;
+}
diff --git a/kpilot/conduits/docconduit/pilotDOCEntry.h b/kpilot/conduits/docconduit/pilotDOCEntry.h
new file mode 100644
index 000000000..b1b9ba45b
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCEntry.h
@@ -0,0 +1,73 @@
+/* pilotDOCEntry.h -*- C++ -*- KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** See the .cc file for an explanation of what this file is for.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to the mailinlist [email protected]
+*/
+#ifndef _KPILOT_PILOTDOCENTRY_H
+#define _KPILOT_PILOTDOCENTRY_H
+
+#include <pilotRecord.h>
+#include "makedoc9.h"
+
+
+class PilotRecord;
+
+
+class PilotDOCEntry:public PilotRecordBase {
+private:
+ bool compress;
+ tBuf fText;
+public:
+ static const int TEXT_SIZE;
+ PilotDOCEntry();
+ PilotDOCEntry(PilotRecord * rec, bool compressed = false);
+ PilotDOCEntry(const PilotDOCEntry & e);
+ ~PilotDOCEntry() {};
+ PilotDOCEntry & operator=(const PilotDOCEntry & e);
+
+
+ QString getText() {
+ fText.Decompress();
+ return QString::fromLatin1((const char *) fText.text());
+ };
+ void setText(QString newtext, bool compressed = false) {
+ fText.setText((const unsigned char *) newtext.latin1(),
+ newtext.length(), compressed);
+ };
+
+ bool getCompress() const {
+ return compress;
+ }
+ void setCompress(bool compressed) {
+ compress = compressed;
+ };
+
+ PilotRecord *pack(); // Not const because it can change the compression
+};
+
+
+
+#endif
+
diff --git a/kpilot/conduits/docconduit/pilotDOCHead.cc b/kpilot/conduits/docconduit/pilotDOCHead.cc
new file mode 100644
index 000000000..1f07e2867
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCHead.cc
@@ -0,0 +1,101 @@
+/* KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** This is a C++ class dealing with PalmDOC text records
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+#include "options.h"
+#include "pilotDOCHead.h"
+
+#include "makedoc9.h"
+
+
+
+const int PilotDOCHead::textRecordSize = 4096;
+
+PilotDOCHead::PilotDOCHead():PilotRecordBase(),
+version(0),
+spare(0), storyLen(0), numRecords(0), recordSize(textRecordSize), position(0)
+{
+ FUNCTIONSETUP;
+}
+
+
+
+/* initialize the entry from another one. If rec==NULL, this constructor does the same as PilotDOCHead()
+*/
+PilotDOCHead::PilotDOCHead(PilotRecord * rec):PilotRecordBase(rec)
+{
+ const unsigned char *b = (const unsigned char *) rec->data();
+ unsigned int offset = 0;
+
+ version = Pilot::dlp<short>::read(b,offset);
+ spare = Pilot::dlp<short>::read(b,offset);
+ storyLen = Pilot::dlp<long>::read(b,offset);
+ numRecords = Pilot::dlp<short>::read(b,offset);
+ recordSize = Pilot::dlp<short>::read(b,offset);
+ position = Pilot::dlp<long>::read(b,offset);
+}
+
+
+PilotDOCHead::PilotDOCHead(const PilotDOCHead & e):PilotRecordBase(e)
+{
+ FUNCTIONSETUP;
+ *this = e;
+}
+
+
+
+PilotDOCHead & PilotDOCHead::operator =(const PilotDOCHead & e)
+{
+ if (this != &e)
+ {
+ version = e.version;
+ spare = e.spare;
+ storyLen = e.storyLen;
+ numRecords = e.numRecords;
+ recordSize = e.recordSize;
+ position = e.position;
+ }
+ return *this;
+}
+
+
+
+
+PilotRecord *PilotDOCHead::pack() const
+{
+ pi_buffer_t *b = pi_buffer_new(16);
+
+ Pilot::dlp<short>::append(b,version);
+ Pilot::dlp<short>::append(b,spare);
+ Pilot::dlp<long>::append(b,storyLen);
+ Pilot::dlp<short>::append(b,numRecords);
+ Pilot::dlp<short>::append(b,recordSize);
+ Pilot::dlp<long>::append(b,position);
+
+ PilotRecord *rec = new PilotRecord(b, this);
+ return rec;
+}
+
diff --git a/kpilot/conduits/docconduit/pilotDOCHead.h b/kpilot/conduits/docconduit/pilotDOCHead.h
new file mode 100644
index 000000000..aeb7fb526
--- /dev/null
+++ b/kpilot/conduits/docconduit/pilotDOCHead.h
@@ -0,0 +1,62 @@
+/* pilotDOCHead.h -*- C++ -*- KPilot
+**
+** Copyright (C) 2002 by Reinhold Kainhofer
+**
+** See the .cc file for an explanation of what this file is for.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to the mailinlist [email protected]
+*/
+#ifndef _KPILOT_PILOTDOCHEAD_H
+#define _KPILOT_PILOTDOCHEAD_H
+
+#include <pilotRecord.h>
+
+class PilotRecord;
+
+
+class PilotDOCHead:public PilotRecordBase {
+ private:
+ static const int textRecordSize;
+
+ public:
+ int version;
+ int spare;
+ long int storyLen;
+ int numRecords;
+ int recordSize;
+ long int position;
+
+ PilotRecord *pack() const;
+
+ public:
+ PilotDOCHead();
+ PilotDOCHead(PilotRecord * rec);
+ PilotDOCHead(const PilotDOCHead & e);
+ ~PilotDOCHead() { }
+
+ PilotDOCHead & operator=(const PilotDOCHead & e);
+};
+
+
+
+#endif
+
diff --git a/kpilot/conduits/docconduit/tests/testcompress.cpp b/kpilot/conduits/docconduit/tests/testcompress.cpp
new file mode 100644
index 000000000..b8367b2b9
--- /dev/null
+++ b/kpilot/conduits/docconduit/tests/testcompress.cpp
@@ -0,0 +1,59 @@
+/*
+** Copyright (C) 2003 by Reinhold Kainhofer
+**
+** This is just a very simple programm to check the compress/uncompress
+** routines by taking one string, compress and then decompress it and
+** see if it is the original string.
+*/
+
+/*
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program in a file called COPYING; if not, write to
+** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+** MA 02110-1301, USA.
+*/
+
+/*
+** Bug reports and questions can be sent to [email protected]
+*/
+#include <stdio.h>
+#include <iostream.h>
+
+
+#include "../makedoc9.h"
+
+void main ()
+{
+ tBuf fText;
+ char*text="asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdf";
+
+ fText.setText((const byte*)text);
+ cout<<"Decompressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+
+ fText.Compress();
+ cout<<" Compressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+ fText.Decompress();
+ cout<<"Decompressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+
+ fText.Compress();
+ cout<<" Compressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+ fText.Decompress();
+ cout<<"Decompressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+
+ fText.Compress();
+ cout<<" Compressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+ fText.Decompress();
+ cout<<"Decompressed text: "<<fText.text()<<" ("<<fText.Len()<<") -- Compressed: "<<fText.compressed()<<endl;
+
+
+}