summaryrefslogtreecommitdiffstats
path: root/src/translators
diff options
context:
space:
mode:
Diffstat (limited to 'src/translators')
-rw-r--r--src/translators/Makefile.am12
-rw-r--r--src/translators/alexandriaexporter.cpp2
-rw-r--r--src/translators/bibteximporter.cpp42
-rw-r--r--src/translators/bibteximporter.h2
-rw-r--r--src/translators/csvimporter.cpp28
-rw-r--r--src/translators/deliciousimporter.cpp17
-rw-r--r--src/translators/freedb_util.cpp2
-rw-r--r--src/translators/htmlexporter.cpp4
-rw-r--r--src/translators/risimporter.cpp23
-rw-r--r--src/translators/risimporter.h2
-rw-r--r--src/translators/tellico_xml.cpp6
-rw-r--r--src/translators/tellico_xml.h2
-rw-r--r--src/translators/tellicoimporter.cpp14
-rw-r--r--src/translators/tellicoimporter.h2
-rw-r--r--src/translators/tellicosaximporter.cpp293
-rw-r--r--src/translators/tellicosaximporter.h87
-rw-r--r--src/translators/tellicoxmlhandler.cpp74
-rw-r--r--src/translators/tellicoxmlhandler.h49
-rw-r--r--src/translators/xmlstatehandler.cpp772
-rw-r--r--src/translators/xmlstatehandler.h345
-rw-r--r--src/translators/xsltexporter.cpp24
-rw-r--r--src/translators/xsltexporter.h4
22 files changed, 1785 insertions, 21 deletions
diff --git a/src/translators/Makefile.am b/src/translators/Makefile.am
index fbbb11b..f0e8520 100644
--- a/src/translators/Makefile.am
+++ b/src/translators/Makefile.am
@@ -12,9 +12,9 @@ libtranslators_a_SOURCES = alexandriaexporter.cpp alexandriaimporter.cpp \
filelistingimporter.cpp freedb_util.cpp freedbimporter.cpp gcfilmsexporter.cpp \
gcfilmsimporter.cpp griffithimporter.cpp grs1importer.cpp htmlexporter.cpp libcsv.c \
onixexporter.cpp pdfimporter.cpp pilotdbexporter.cpp referencerimporter.cpp \
- risimporter.cpp tellico_xml.cpp tellicoimporter.cpp tellicoxmlexporter.cpp \
- tellicozipexporter.cpp textimporter.cpp xmlimporter.cpp xsltexporter.cpp xslthandler.cpp \
- xsltimporter.cpp
+ risimporter.cpp tellico_xml.cpp tellicoimporter.cpp tellicosaximporter.cpp \
+ tellicoxmlexporter.cpp tellicoxmlhandler.cpp tellicozipexporter.cpp textimporter.cpp \
+ xmlimporter.cpp xmlstatehandler.cpp xsltexporter.cpp xslthandler.cpp xsltimporter.cpp
if !USE_LIBBTPARSE
SUBDIR_LIBBTPARSE = btparse
@@ -51,7 +51,10 @@ dcimporter.h dcimporter.cpp griffithimporter.h \
griffithimporter.cpp griffith2tellico.py pdfimporter.h \
pdfimporter.cpp referencerimporter.h referencerimporter.cpp \
libcsv.h libcsv.c \
-deliciousimporter.h deliciousimporter.cpp
+deliciousimporter.h deliciousimporter.cpp \
+tellicosaximporter.h tellicosaximporter.cpp \
+tellicoxmlhandler.h tellicoxmlhandler.cpp \
+xmlstatehandler.h xmlstatehandler.cpp
####### tdevelop will overwrite this part!!! (end)############
@@ -68,3 +71,4 @@ KDE_OPTIONS = noautodist
appdir = $(kde_datadir)/tellico
app_DATA = bibtex-translation.xml
app_SCRIPTS = griffith2tellico.py
+
diff --git a/src/translators/alexandriaexporter.cpp b/src/translators/alexandriaexporter.cpp
index de64fbb..633864f 100644
--- a/src/translators/alexandriaexporter.cpp
+++ b/src/translators/alexandriaexporter.cpp
@@ -77,7 +77,7 @@ bool AlexandriaExporter::exec() {
ProgressItem& item = ProgressManager::self()->newProgressItem(this, TQString(), false);
item.setTotalSteps(entries().count());
ProgressItem::Done done(this);
- const uint stepSize = TQMIN(1, entries().count()/100);
+ const uint stepSize = TQMAX(1, entries().count()/100);
const bool showProgress = options() & ExportProgress;
GUI::CursorSaver cs;
diff --git a/src/translators/bibteximporter.cpp b/src/translators/bibteximporter.cpp
index fb52f95..d3668d4 100644
--- a/src/translators/bibteximporter.cpp
+++ b/src/translators/bibteximporter.cpp
@@ -308,5 +308,47 @@ TQWidget* BibtexImporter::widget(TQWidget* parent_, const char* name_/*=0*/) {
return m_widget;
}
+bool BibtexImporter::maybeBibtex(const KURL& url_) {
+ TQString text = FileHandler::readTextFile(url_, true /*quiet*/);
+ if(text.isEmpty()) {
+ return false;
+ }
+
+ bt_initialize();
+ TQRegExp rx(TQString::fromLatin1("[{}]"));
+
+ ushort bt_options = 0; // ushort is defined in btparse.h
+ boolean ok; // boolean is defined in btparse.h as an int
+ bool foundOne = false;
+ int brace = 0;
+ int startpos = 0;
+ int pos = text.find(rx, 0);
+ while(pos > 0) {
+ if(text[pos] == '{') {
+ ++brace;
+ } else if(text[pos] == '}' && brace > 0) {
+ --brace;
+ }
+ if(brace == 0) {
+ TQString entry = text.mid(startpos, pos-startpos+1).stripWhiteSpace();
+ // All the downstream text processing on the AST node will assume utf-8
+ AST* node = bt_parse_entry_s(const_cast<char*>(entry.utf8().data()),
+ const_cast<char*>(url_.fileName().local8Bit().data()),
+ 0, bt_options, &ok);
+ if(ok && node) {
+ foundOne = true;
+ break;
+ }
+ startpos = pos+1;
+ }
+ pos = text.find(rx, pos+1);
+ }
+ if(foundOne) {
+ // clean up some structures
+ bt_parse_entry_s(0, 0, 1, 0, 0);
+ }
+ bt_cleanup();
+ return foundOne;
+}
#include "bibteximporter.moc"
diff --git a/src/translators/bibteximporter.h b/src/translators/bibteximporter.h
index 6d1b878..09e1ec3 100644
--- a/src/translators/bibteximporter.h
+++ b/src/translators/bibteximporter.h
@@ -67,6 +67,8 @@ public:
virtual TQWidget* widget(TQWidget* parent, const char* name=0);
virtual bool canImport(int type) const;
+ static bool maybeBibtex(const KURL& url);
+
public slots:
void slotCancel();
diff --git a/src/translators/csvimporter.cpp b/src/translators/csvimporter.cpp
index 8a53ff9..d6198d0 100644
--- a/src/translators/csvimporter.cpp
+++ b/src/translators/csvimporter.cpp
@@ -50,15 +50,26 @@ extern "C" {
using Tellico::Import::CSVImporter;
+typedef int(*SpaceFunc)(char);
+
static void writeToken(char* buffer, size_t len, void* data);
static void writeRow(char buffer, void* data);
+static int isSpace(char c);
+static int isSpaceOrTab(char c);
+static int isTab(char c);
class CSVImporter::Parser {
public:
Parser(const TQString& str) : stream(new TQTextIStream(&str)) { csv_init(&parser, 0); }
~Parser() { csv_free(parser); delete stream; stream = 0; }
- void setDelimiter(const TQString& s) { Q_ASSERT(s.length() == 1); csv_set_delim(parser, s[0].latin1()); }
+ void setDelimiter(const TQString& s) {
+ Q_ASSERT(s.length() == 1);
+ csv_set_delim(parser, s[0].latin1());
+ if(s[0] == '\t') csv_set_space_func(parser, isSpace);
+ else if(s[0] == ' ') csv_set_space_func(parser, isTab);
+ else csv_set_space_func(parser, isSpaceOrTab);
+ }
void reset(const TQString& str) { delete stream; stream = new TQTextIStream(&str); };
bool hasNext() { return !stream->atEnd(); }
void skipLine() { stream->readLine(); }
@@ -95,6 +106,21 @@ static void writeRow(char c, void* data) {
p->setRowDone(true);
}
+static int isSpace(char c) {
+ if (c == CSV_SPACE) return 1;
+ return 0;
+}
+
+static int isSpaceOrTab(char c) {
+ if (c == CSV_SPACE || c == CSV_TAB) return 1;
+ return 0;
+}
+
+static int isTab(char c) {
+ if (c == CSV_TAB) return 1;
+ return 0;
+}
+
CSVImporter::CSVImporter(const KURL& url_) : Tellico::Import::TextImporter(url_),
m_coll(0),
m_existingCollection(0),
diff --git a/src/translators/deliciousimporter.cpp b/src/translators/deliciousimporter.cpp
index a82c006..be6fe3e 100644
--- a/src/translators/deliciousimporter.cpp
+++ b/src/translators/deliciousimporter.cpp
@@ -35,7 +35,9 @@ DeliciousImporter::DeliciousImporter(const KURL& url_) : XSLTImporter(url_) {
}
bool DeliciousImporter::canImport(int type) const {
- return type == Data::Collection::Book;
+ return type == Data::Collection::Book ||
+ type == Data::Collection::Video ||
+ type == Data::Collection::Game;
}
Tellico::Data::CollPtr DeliciousImporter::collection() {
@@ -51,7 +53,18 @@ Tellico::Data::CollPtr DeliciousImporter::collection() {
<< TQString::fromLatin1("Medium Covers/")
<< TQString::fromLatin1("Small Covers/")
<< TQString::fromLatin1("Plain Covers/");
- const TQString commField = TQString::fromLatin1("comments");
+ TQString commField;
+ switch(coll->type()) {
+ case Data::Collection::Book:
+ commField = TQString::fromLatin1("comments"); break;
+ case Data::Collection::Video:
+ commField = TQString::fromLatin1("plot"); break;
+ case Data::Collection::Game:
+ commField = TQString::fromLatin1("description"); break;
+ default:
+ myWarning() << "bad collection type:" << coll->type() << endl;
+ }
+
const TQString uuidField = TQString::fromLatin1("uuid");
const TQString coverField = TQString::fromLatin1("cover");
const bool isLocal = url().isLocalFile();
diff --git a/src/translators/freedb_util.cpp b/src/translators/freedb_util.cpp
index 07292af..2a2e5ed 100644
--- a/src/translators/freedb_util.cpp
+++ b/src/translators/freedb_util.cpp
@@ -365,7 +365,7 @@ FreeDBImporter::CDText FreeDBImporter::getCDText(const TQCString& drive_) {
}
}
if(cdtext.trackTitles.size() != cdtext.trackArtists.size()) {
- int size = TQMAX(cdtext.trackTitles.size(), cdtext.trackArtists.size());
+ size_t size = TQMAX(cdtext.trackTitles.size(), cdtext.trackArtists.size());
cdtext.trackTitles.resize(size);
cdtext.trackArtists.resize(size);
}
diff --git a/src/translators/htmlexporter.cpp b/src/translators/htmlexporter.cpp
index e27d6e5..e8bb95d 100644
--- a/src/translators/htmlexporter.cpp
+++ b/src/translators/htmlexporter.cpp
@@ -31,6 +31,7 @@
#include <tdeio/netaccess.h>
#include <tdeapplication.h>
#include <tdelocale.h>
+#include <kuser.h>
#include <tqdom.h>
#include <tqgroupbox.h>
@@ -192,6 +193,9 @@ bool HTMLExporter::loadXSLTFile() {
m_handler = 0;
return false;
}
+ m_handler->addStringParam("date", TQDate::currentDate().toString(TQt::ISODate).latin1());
+ m_handler->addStringParam("time", TQTime::currentTime().toString(TQt::ISODate).latin1());
+ m_handler->addStringParam("user", KUser(KUser::UseRealUserID).loginName().latin1());
if(m_exportEntryFiles) {
// export entries to same place as all the other date files
diff --git a/src/translators/risimporter.cpp b/src/translators/risimporter.cpp
index 735368c..0158708 100644
--- a/src/translators/risimporter.cpp
+++ b/src/translators/risimporter.cpp
@@ -188,7 +188,7 @@ void RISImporter::readURL(const KURL& url_, int n, const TQDict<Data::Field>& ri
// technically, the spec requires a space immediately after the hyphen
// however, at least one website (Springer) outputs RIS with no space after the final "ER -"
// so just strip the white space later
- // also be gracious and allow only any amount of space before hyphen
+ // also be gracious and allow any amount of space before hyphen
TQRegExp rx(TQString::fromLatin1("^(\\w\\w)\\s+-(.*)$"));
TQString currLine, nextLine;
for(currLine = t.readLine(); !m_cancelled && !currLine.isNull(); currLine = nextLine, j += currLine.length()) {
@@ -312,4 +312,25 @@ void RISImporter::slotCancel() {
m_cancelled = true;
}
+bool RISImporter::maybeRIS(const KURL& url_) {
+ TQString text = FileHandler::readTextFile(url_, true /*quiet*/);
+ if(text.isEmpty()) {
+ return false;
+ }
+
+ // bare bones check, strip white space at beginning
+ // and then first text line must be valid RIS
+ TQTextIStream t(&text);
+
+ TQRegExp rx(TQString::fromLatin1("^(\\w\\w)\\s+-(.*)$"));
+ TQString currLine;
+ for(currLine = t.readLine(); !currLine.isNull(); currLine = t.readLine()) {
+ if(currLine.stripWhiteSpace().isEmpty()) {
+ continue;
+ }
+ break;
+ }
+ return rx.exactMatch(currLine);
+}
+
#include "risimporter.moc"
diff --git a/src/translators/risimporter.h b/src/translators/risimporter.h
index fa581ba..a572283 100644
--- a/src/translators/risimporter.h
+++ b/src/translators/risimporter.h
@@ -50,6 +50,8 @@ public:
virtual TQWidget* widget(TQWidget*, const char*) { return 0; }
virtual bool canImport(int type) const;
+ static bool maybeRIS(const KURL& url);
+
public slots:
void slotCancel();
diff --git a/src/translators/tellico_xml.cpp b/src/translators/tellico_xml.cpp
index bcfb412..3a927d6 100644
--- a/src/translators/tellico_xml.cpp
+++ b/src/translators/tellico_xml.cpp
@@ -63,6 +63,12 @@ TQString Tellico::XML::dtdTellico(int version) {
return TQString::fromLatin1("http://periapsis.org/tellico/dtd/v%1/tellico.dtd").arg(version);
}
+// returns true if the file has to be converted
+// version 9 to 10 requires no conversion since it only added board games
+bool Tellico::XML::versionConversion(uint from, uint to) {
+ return from < to && (from != 9 || to != 10);
+}
+
bool Tellico::XML::validXMLElementName(const TQString& name_) {
return xmlValidateNameValue((xmlChar *)name_.utf8().data());
}
diff --git a/src/translators/tellico_xml.h b/src/translators/tellico_xml.h
index 6ff4c1b..6ffda10 100644
--- a/src/translators/tellico_xml.h
+++ b/src/translators/tellico_xml.h
@@ -28,6 +28,8 @@ namespace Tellico {
TQString pubTellico(int version = syntaxVersion);
TQString dtdTellico(int version = syntaxVersion);
+ bool versionConversion(uint from, uint to);
+
extern const TQString nsBookcase;
extern const TQString nsDublinCore;
extern const TQString nsZing;
diff --git a/src/translators/tellicoimporter.cpp b/src/translators/tellicoimporter.cpp
index a8dfb62..d722c0c 100644
--- a/src/translators/tellicoimporter.cpp
+++ b/src/translators/tellicoimporter.cpp
@@ -39,11 +39,6 @@
using Tellico::Import::TellicoImporter;
-bool TellicoImporter::versionConversion(uint from, uint to) {
- // version 10 only added board games to version 9
- return from < to && (from != 9 || to != 10);
-}
-
TellicoImporter::TellicoImporter(const KURL& url_, bool loadAllImages_) : DataImporter(url_),
m_coll(0), m_loadAllImages(loadAllImages_), m_format(Unknown), m_modified(false),
m_cancelled(false), m_hasImages(false), m_buffer(0), m_zip(0), m_imgDir(0) {
@@ -157,7 +152,7 @@ void TellicoImporter::loadXMLData(const TQByteArray& data_, bool loadImages_) {
}
m_format = Error;
return;
- } else if(versionConversion(syntaxVersion, XML::syntaxVersion)) {
+ } else if(XML::versionConversion(syntaxVersion, XML::syntaxVersion)) {
// going form version 9 to 10, there's no conversion needed
TQString str = i18n("Tellico is converting the file to a more recent document format. "
"Information loss may occur if an older version of Tellico is used "
@@ -374,7 +369,7 @@ void TellicoImporter::readField(uint syntaxVersion_, const TQDomElement& elem_)
Data::FieldPtr field;
if(type == Data::Field::Choice) {
- TQStringList allowed = TQStringList::split(TQString::fromLatin1(";"),
+ TQStringList allowed = TQStringList::split(TQRegExp(TQString::fromLatin1("\\s*;\\s*")),
elem_.attribute(TQString::fromLatin1("allowed")));
if(isI18n) {
for(TQStringList::Iterator it = allowed.begin(); it != allowed.end(); ++it) {
@@ -652,8 +647,9 @@ void TellicoImporter::readEntry(uint syntaxVersion_, const TQDomElement& entryEl
void TellicoImporter::readImage(const TQDomElement& elem_, bool loadImage_) {
TQString format = elem_.attribute(TQString::fromLatin1("format"));
const bool link = elem_.attribute(TQString::fromLatin1("link")) == Latin1Literal("true");
- TQString id = shareString(link ? elem_.attribute(TQString::fromLatin1("id"))
- : Data::Image::idClean(elem_.attribute(TQString::fromLatin1("id"))));
+ // idClean() already calls shareString()
+ TQString id = link ? shareString(elem_.attribute(TQString::fromLatin1("id")))
+ : Data::Image::idClean(elem_.attribute(TQString::fromLatin1("id")));
bool readInfo = true;
if(loadImage_) {
diff --git a/src/translators/tellicoimporter.h b/src/translators/tellicoimporter.h
index 93cf7da..6ea0ac5 100644
--- a/src/translators/tellicoimporter.h
+++ b/src/translators/tellicoimporter.h
@@ -70,8 +70,6 @@ public slots:
void slotCancel();
private:
- static bool versionConversion(uint from, uint to);
-
void loadXMLData(const TQByteArray& data, bool loadImages);
void loadZipData();
diff --git a/src/translators/tellicosaximporter.cpp b/src/translators/tellicosaximporter.cpp
new file mode 100644
index 0000000..de60c63
--- /dev/null
+++ b/src/translators/tellicosaximporter.cpp
@@ -0,0 +1,293 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+// before tellicosaxmporter.h because of QT_NO_CAST_ASCII issues
+#include "tellicoxmlhandler.h"
+#include "tellicosaximporter.h"
+#include "tellico_xml.h"
+#include "../collectionfactory.h"
+#include "../collections/bibtexcollection.h"
+#include "../entry.h"
+#include "../field.h"
+#include "../imagefactory.h"
+#include "../image.h"
+#include "../isbnvalidator.h"
+#include "../latin1literal.h"
+#include "../tellico_strings.h"
+#include "../tellico_kernel.h"
+#include "../tellico_utils.h"
+#include "../tellico_debug.h"
+#include "../progressmanager.h"
+
+#include <tdelocale.h>
+#include <kmdcodec.h>
+#include <kzip.h>
+#include <tdeapplication.h>
+
+#include <tqbuffer.h>
+#include <tqfile.h>
+#include <tqtimer.h>
+
+using Tellico::Import::TellicoSaxImporter;
+
+TellicoSaxImporter::TellicoSaxImporter(const KURL& url_, bool loadAllImages_) : DataImporter(url_),
+ m_coll(0), m_loadAllImages(loadAllImages_), m_format(Unknown), m_modified(false),
+ m_cancelled(false), m_hasImages(false), m_buffer(0), m_zip(0), m_imgDir(0) {
+}
+
+TellicoSaxImporter::TellicoSaxImporter(const TQString& text_) : DataImporter(text_),
+ m_coll(0), m_loadAllImages(true), m_format(Unknown), m_modified(false),
+ m_cancelled(false), m_hasImages(false), m_buffer(0), m_zip(0), m_imgDir(0) {
+}
+
+TellicoSaxImporter::~TellicoSaxImporter() {
+ if(m_zip) {
+ m_zip->close();
+ }
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+}
+
+Tellico::Data::CollPtr TellicoSaxImporter::collection() {
+ if(m_coll) {
+ return m_coll;
+ }
+
+ TQCString s; // read first 5 characters
+ if(source() == URL) {
+ if(!fileRef().open()) {
+ return 0;
+ }
+ TQIODevice* f = fileRef().file();
+ for(uint i = 0; i < 5; ++i) {
+ s += static_cast<char>(f->getch());
+ }
+ f->reset();
+ } else {
+ if(data().size() < 5) {
+ m_format = Error;
+ return 0;
+ }
+ s = TQCString(data(), 6);
+ }
+
+ // need to decide if the data is xml text, or a zip file
+ // if the first 5 characters are <?xml then treat it like text
+ if(s[0] == '<' && s[1] == '?' && s[2] == 'x' && s[3] == 'm' && s[4] == 'l') {
+ m_format = XML;
+ loadXMLData(source() == URL ? fileRef().file()->readAll() : data(), true);
+ } else {
+ m_format = Zip;
+ loadZipData();
+ }
+ return m_coll;
+}
+
+void TellicoSaxImporter::loadXMLData(const TQByteArray& data_, bool loadImages_) {
+ ProgressItem& item = ProgressManager::self()->newProgressItem(this, progressLabel(), true);
+ item.setTotalSteps(data_.size());
+ connect(&item, SIGNAL(signalCancelled(ProgressItem*)), SLOT(slotCancel()));
+ ProgressItem::Done done(this);
+
+ const bool showProgress = options() & ImportProgress;
+
+ TellicoXMLHandler handler;
+ handler.setLoadImages(loadImages_);
+
+ TQXmlSimpleReader reader;
+ reader.setContentHandler(&handler);
+
+ TQXmlInputSource source;
+ bool success = reader.parse(&source, true);
+
+ const uint blockSize = data_.size()/100 + 1;
+ uint pos = 0;
+ TQByteArray block;
+
+ while(success && !m_cancelled && pos < data_.size()) {
+ uint size = TQMIN(blockSize, data_.size() - pos);
+ block.setRawData(data_.data() + pos, size);
+ source.setData(block);
+ success = reader.parseContinue();
+ block.resetRawData(data_.data() + pos, size);
+ pos += blockSize;
+ if(showProgress) {
+ ProgressManager::self()->setProgress(this, pos);
+ kapp->processEvents();
+ }
+ }
+
+ if(!success) {
+ m_format = Error;
+ TQString error;
+ if(!url().isEmpty()) {
+ error = i18n(errorLoad).arg(url().fileName()) + TQChar('\n');
+ }
+ error += handler.errorString();
+ myDebug() << error << endl;
+ setStatusMessage(error);
+ return;
+ }
+
+ if(!m_cancelled) {
+ m_hasImages = handler.hasImages();
+ m_coll = handler.collection();
+ }
+}
+
+void TellicoSaxImporter::loadZipData() {
+ delete m_buffer;
+ delete m_zip;
+ if(source() == URL) {
+ m_buffer = 0;
+ m_zip = new KZip(fileRef().fileName());
+ } else {
+ m_buffer = new TQBuffer(data());
+ m_zip = new KZip(m_buffer);
+ }
+ if(!m_zip->open(IO_ReadOnly)) {
+ setStatusMessage(i18n(errorLoad).arg(url().fileName()));
+ m_format = Error;
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+
+ const KArchiveDirectory* dir = m_zip->directory();
+ if(!dir) {
+ TQString str = i18n(errorLoad).arg(url().fileName()) + TQChar('\n');
+ str += i18n("The file is empty.");
+ setStatusMessage(str);
+ m_format = Error;
+ m_zip->close();
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+
+ // main file was changed from bookcase.xml to tellico.xml as of version 0.13
+ const KArchiveEntry* entry = dir->entry(TQString::fromLatin1("tellico.xml"));
+ if(!entry) {
+ entry = dir->entry(TQString::fromLatin1("bookcase.xml"));
+ }
+ if(!entry || !entry->isFile()) {
+ TQString str = i18n(errorLoad).arg(url().fileName()) + TQChar('\n');
+ str += i18n("The file contains no collection data.");
+ setStatusMessage(str);
+ m_format = Error;
+ m_zip->close();
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+
+ const TQByteArray xmlData = static_cast<const KArchiveFile*>(entry)->data();
+ loadXMLData(xmlData, false);
+ if(!m_coll) {
+ m_format = Error;
+ m_zip->close();
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+
+ if(m_cancelled) {
+ m_zip->close();
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+
+ const KArchiveEntry* imgDirEntry = dir->entry(TQString::fromLatin1("images"));
+ if(!imgDirEntry || !imgDirEntry->isDirectory()) {
+ m_zip->close();
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+ m_imgDir = static_cast<const KArchiveDirectory*>(imgDirEntry);
+ m_images.clear();
+ m_images.add(m_imgDir->entries());
+ m_hasImages = !m_images.isEmpty();
+
+ // if all the images are not to be loaded, then we're done
+ if(!m_loadAllImages) {
+// myLog() << "TellicoSaxImporter::loadZipData() - delayed loading for " << m_images.count() << " images" << endl;
+ return;
+ }
+
+ const TQStringList images = static_cast<const KArchiveDirectory*>(imgDirEntry)->entries();
+ const uint stepSize = TQMAX(s_stepSize, images.count()/100);
+
+ uint j = 0;
+ for(TQStringList::ConstIterator it = images.begin(); !m_cancelled && it != images.end(); ++it, ++j) {
+ const KArchiveEntry* file = m_imgDir->entry(*it);
+ if(file && file->isFile()) {
+ ImageFactory::addImage(static_cast<const KArchiveFile*>(file)->data(),
+ (*it).section('.', -1).upper(), (*it));
+ m_images.remove(*it);
+ }
+ if(j%stepSize == 0) {
+ kapp->processEvents();
+ }
+ }
+
+ if(m_images.isEmpty()) {
+ // give it some time
+ TQTimer::singleShot(3000, this, SLOT(deleteLater()));
+ }
+}
+
+bool TellicoSaxImporter::hasImages() const {
+ return m_hasImages;
+}
+
+bool TellicoSaxImporter::loadImage(const TQString& id_) {
+// myLog() << "TellicoSaxImporter::loadImage() - id = " << id_ << endl;
+ if(m_format != Zip || !m_imgDir) {
+ return false;
+ }
+ const KArchiveEntry* file = m_imgDir->entry(id_);
+ if(!file || !file->isFile()) {
+ return false;
+ }
+ TQString newID = ImageFactory::addImage(static_cast<const KArchiveFile*>(file)->data(),
+ id_.section('.', -1).upper(), id_);
+ m_images.remove(id_);
+ if(m_images.isEmpty()) {
+ // give it some time
+ TQTimer::singleShot(3000, this, SLOT(deleteLater()));
+ }
+ return !newID.isEmpty();
+}
+
+void TellicoSaxImporter::slotCancel() {
+ m_cancelled = true;
+ m_format = Cancel;
+}
+
+#include "tellicosaximporter.moc"
diff --git a/src/translators/tellicosaximporter.h b/src/translators/tellicosaximporter.h
new file mode 100644
index 0000000..056f60f
--- /dev/null
+++ b/src/translators/tellicosaximporter.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef TELLICO_IMPORT_TELLICOSAXIMPORTER_H
+#define TELLICO_IMPORT_TELLICOSAXIMPORTER_H
+
+#include "dataimporter.h"
+#include "../datavectors.h"
+#include "../stringset.h"
+
+class TQBuffer;
+class KZip;
+class KArchiveDirectory;
+
+namespace Tellico {
+ namespace Import {
+
+/**
+ * @author Robby Stephenson
+ */
+class TellicoSaxImporter : public DataImporter {
+Q_OBJECT
+
+public:
+ enum Format { Unknown, Error, XML, Zip, Cancel };
+
+ /**
+ * @param url The tellico data file.
+ */
+ TellicoSaxImporter(const KURL& url, bool loadAllImages=true);
+ /**
+ * Constructor used to convert arbitrary text to a @ref Collection
+ *
+ * @param text The text
+ */
+ TellicoSaxImporter(const TQString& text);
+ virtual ~TellicoSaxImporter();
+
+ /**
+ * sometimes, a new document format might add data
+ */
+ bool modifiedOriginal() const { return m_modified; }
+
+ /**
+ */
+ virtual Data::CollPtr collection();
+ Format format() const { return m_format; }
+
+ bool hasImages() const;
+ bool loadImage(const TQString& id_);
+
+ static bool loadAllImages(const KURL& url);
+
+public slots:
+ void slotCancel();
+
+private:
+ void loadXMLData(const TQByteArray& data, bool loadImages);
+ void loadZipData();
+
+ Data::CollPtr m_coll;
+ bool m_loadAllImages;
+ TQString m_namespace;
+ Format m_format;
+ bool m_modified : 1;
+ bool m_cancelled : 1;
+ bool m_hasImages : 1;
+ StringSet m_images;
+
+ TQBuffer* m_buffer;
+ KZip* m_zip;
+ const KArchiveDirectory* m_imgDir;
+};
+
+ } // end namespace
+} // end namespace
+#endif
diff --git a/src/translators/tellicoxmlhandler.cpp b/src/translators/tellicoxmlhandler.cpp
new file mode 100644
index 0000000..5b3f063
--- /dev/null
+++ b/src/translators/tellicoxmlhandler.cpp
@@ -0,0 +1,74 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include "tellicoxmlhandler.h"
+#include "../collection.h"
+#include "../tellico_debug.h"
+
+using Tellico::Import::TellicoXMLHandler;
+
+TellicoXMLHandler::TellicoXMLHandler() : TQXmlDefaultHandler(), m_data(new SAX::StateData) {
+ m_handlers.setAutoDelete(true);
+ m_handlers.push(new SAX::RootHandler(m_data));
+}
+
+TellicoXMLHandler::~TellicoXMLHandler() {
+ delete m_data;
+ m_data = 0;
+}
+
+bool TellicoXMLHandler::startElement(const TQString& nsURI_, const TQString& localName_,
+ const TQString& qName_, const TQXmlAttributes& atts_) {
+ SAX::StateHandler* handler = m_handlers.top()->nextHandler(nsURI_, localName_, qName_);
+ Q_ASSERT(handler);
+ m_handlers.push(handler);
+ return handler->start(nsURI_, localName_, qName_, atts_);
+}
+
+bool TellicoXMLHandler::endElement(const TQString& nsURI_, const TQString& localName_,
+ const TQString& qName_) {
+ m_data->text = m_data->text.stripWhiteSpace();
+/*
+ if(!m_data->text.isEmpty()) {
+ myDebug() << " text: " << m_text << endl;
+ }
+*/
+
+ SAX::StateHandler* handler = m_handlers.pop();
+ bool res = handler->end(nsURI_, localName_, qName_);
+ // need to reset character data, too
+ m_data->text = TQString();
+ delete handler;
+ return res;
+}
+
+bool TellicoXMLHandler::characters(const TQString& ch_) {
+ m_data->text += ch_;
+ return true;
+}
+
+TQString TellicoXMLHandler::errorString() {
+ return m_data->error;
+}
+
+Tellico::Data::CollPtr TellicoXMLHandler::collection() const {
+ return m_data->coll;
+}
+
+bool TellicoXMLHandler::hasImages() const {
+ return m_data->hasImages;
+}
+
+void TellicoXMLHandler::setLoadImages(bool loadImages_) {
+ m_data->loadImages = loadImages_;
+}
diff --git a/src/translators/tellicoxmlhandler.h b/src/translators/tellicoxmlhandler.h
new file mode 100644
index 0000000..1edeacc
--- /dev/null
+++ b/src/translators/tellicoxmlhandler.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef TELLICO_IMPORT_TELLICOXMLHANDLER_H
+#define TELLICO_IMPORT_TELLICOXMLHANDLER_H
+
+#include "xmlstatehandler.h"
+
+#include <tqptrstack.h>
+
+namespace Tellico {
+ namespace Import {
+
+class TellicoXMLHandler : public TQXmlDefaultHandler {
+public:
+ TellicoXMLHandler();
+ ~TellicoXMLHandler();
+
+ virtual bool startElement(const TQString& namespaceURI, const TQString& localName,
+ const TQString& qName, const TQXmlAttributes& atts);
+ virtual bool endElement(const TQString& namespaceURI, const TQString& localName,
+ const TQString& qName);
+ virtual bool characters(const TQString& ch);
+
+ virtual TQString errorString();
+
+ Data::CollPtr collection() const;
+ bool hasImages() const;
+
+ void setLoadImages(bool loadImages);
+
+private:
+ TQPtrStack<SAX::StateHandler> m_handlers;
+ SAX::StateData* m_data;
+};
+
+ }
+}
+#endif
diff --git a/src/translators/xmlstatehandler.cpp b/src/translators/xmlstatehandler.cpp
new file mode 100644
index 0000000..48d52d6
--- /dev/null
+++ b/src/translators/xmlstatehandler.cpp
@@ -0,0 +1,772 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include "xmlstatehandler.h"
+#include "tellico_xml.h"
+#include "../latin1literal.h"
+#include "../collection.h"
+#include "../collectionfactory.h"
+#include "../collections/bibtexcollection.h"
+#include "../image.h"
+#include "../imagefactory.h"
+#include "../isbnvalidator.h"
+#include "../tellico_utils.h"
+#include "../tellico_debug.h"
+
+#include <tdelocale.h>
+#include <kmdcodec.h>
+
+namespace {
+
+inline
+TQString attValue(const TQXmlAttributes& atts, const char* name, const TQString& defaultValue=TQString()) {
+ int idx = atts.index(TQString::fromLatin1(name));
+ return idx < 0 ? defaultValue : atts.value(idx);
+}
+
+inline
+TQString attValue(const TQXmlAttributes& atts, const char* name, const char* defaultValue) {
+ Q_ASSERT(defaultValue);
+ return attValue(atts, name, TQString::fromLatin1(defaultValue));
+}
+
+}
+
+using Tellico::Import::SAX::StateHandler;
+using Tellico::Import::SAX::NullHandler;
+using Tellico::Import::SAX::RootHandler;
+using Tellico::Import::SAX::DocumentHandler;
+using Tellico::Import::SAX::CollectionHandler;
+using Tellico::Import::SAX::FieldsHandler;
+using Tellico::Import::SAX::FieldHandler;
+using Tellico::Import::SAX::FieldPropertyHandler;
+using Tellico::Import::SAX::BibtexPreambleHandler;
+using Tellico::Import::SAX::BibtexMacrosHandler;
+using Tellico::Import::SAX::BibtexMacroHandler;
+using Tellico::Import::SAX::EntryHandler;
+using Tellico::Import::SAX::FieldValueContainerHandler;
+using Tellico::Import::SAX::FieldValueHandler;
+using Tellico::Import::SAX::DateValueHandler;
+using Tellico::Import::SAX::TableColumnHandler;
+using Tellico::Import::SAX::ImagesHandler;
+using Tellico::Import::SAX::ImageHandler;
+using Tellico::Import::SAX::FiltersHandler;
+using Tellico::Import::SAX::FilterHandler;
+using Tellico::Import::SAX::FilterRuleHandler;
+using Tellico::Import::SAX::BorrowersHandler;
+using Tellico::Import::SAX::BorrowerHandler;
+using Tellico::Import::SAX::LoanHandler;
+
+StateHandler* StateHandler::nextHandler(const TQString& ns_, const TQString& localName_, const TQString& qName_) {
+ StateHandler* handler = nextHandlerImpl(ns_, localName_, qName_);
+ if(!handler) {
+ myWarning() << "StateHandler::nextHandler() - no handler for " << localName_ << endl;
+ }
+ return handler ? handler : new NullHandler(d);
+}
+
+StateHandler* RootHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("tellico") || localName_ == Latin1Literal("bookcase")) {
+ return new DocumentHandler(d);
+ }
+ return new RootHandler(d);
+}
+
+StateHandler* DocumentHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("collection")) {
+ return new CollectionHandler(d);
+ } else if(localName_ == Latin1Literal("filters")) {
+ return new FiltersHandler(d);
+ } else if(localName_ == Latin1Literal("borrowers")) {
+ return new BorrowersHandler(d);
+ }
+ return 0;
+}
+
+bool DocumentHandler::start(const TQString&, const TQString& localName_, const TQString&, const TQXmlAttributes& atts_) {
+ // the syntax version field name changed from "version" to "syntaxVersion" in version 3
+ int idx = atts_.index(TQString::fromLatin1("syntaxVersion"));
+ if(idx < 0) {
+ idx = atts_.index(TQString::fromLatin1("version"));
+ }
+ if(idx < 0) {
+ myWarning() << "RootHandler::start() - no syntax version" << endl;
+ return false;
+ }
+ d->syntaxVersion = atts_.value(idx).toUInt();
+ if(d->syntaxVersion > Tellico::XML::syntaxVersion) {
+ d->error = i18n("It is from a future version of Tellico.");
+ return false;
+ } else if(Tellico::XML::versionConversion(d->syntaxVersion, Tellico::XML::syntaxVersion)) {
+ // going from version 9 to 10, there's no conversion needed
+ TQString str = i18n("Tellico is converting the file to a more recent document format. "
+ "Information loss may occur if an older version of Tellico is used "
+ "to read this file in the future.");
+ myDebug() << str << endl;
+ }
+ if((d->syntaxVersion > 6 && localName_ != Latin1Literal("tellico")) ||
+ (d->syntaxVersion < 7 && localName_ != Latin1Literal("bookcase"))) {
+ // no error message
+ myWarning() << "RootHandler::start() - bad root element name" << endl;
+ return false;
+ }
+ d->ns = d->syntaxVersion > 6 ? Tellico::XML::nsTellico : Tellico::XML::nsBookcase;
+ return true;
+}
+
+bool DocumentHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* CollectionHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if((d->syntaxVersion > 3 && localName_ == Latin1Literal("fields")) ||
+ (d->syntaxVersion < 4 && localName_ == Latin1Literal("attributes"))) {
+ return new FieldsHandler(d);
+ } else if(localName_ == Latin1Literal("bibtex-preamble")) {
+ return new BibtexPreambleHandler(d);
+ } else if(localName_ == Latin1Literal("macros")) {
+ return new BibtexMacrosHandler(d);
+ } else if(localName_ == d->entryName) {
+ return new EntryHandler(d);
+ } else if(localName_ == Latin1Literal("images")) {
+ return new ImagesHandler(d);
+ }
+ return 0;
+}
+
+bool CollectionHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ d->collTitle = attValue(atts_, "title");
+ d->collType = attValue(atts_, "type").toInt();
+ d->entryName = attValue(atts_, "unit");
+
+ Q_ASSERT(d->collType);
+ return true;
+}
+
+bool CollectionHandler::end(const TQString&, const TQString&, const TQString&) {
+ d->coll->addEntries(d->entries);
+ // a little hidden capability was to just have a local path as an image file name
+ // and on reading the xml file, Tellico would load the image file, too
+ // here, we need to scan all the image values in all the entries and check
+ // maybe this is too costly, especially since the capability wasn't advertised?
+ Data::FieldVec fields = d->coll->imageFields();
+ for(Data::EntryVecIt entry = d->entries.begin(); entry != d->entries.end(); ++entry) {
+ for(Data::FieldVecIt field = fields.begin(); field != fields.end(); ++field) {
+ TQString value = entry->field(field, false);
+ // image info should have already been loaded
+ const Data::ImageInfo& info = ImageFactory::imageInfo(value);
+ // possible that value needs to be cleaned first in which case info is null
+ if(info.isNull() || !info.linkOnly) {
+ // for local files only, allow paths here
+ KURL u = KURL::fromPathOrURL(value);
+ if(u.isValid() && u.isLocalFile()) {
+ TQString result = ImageFactory::addImage(u, false /* quiet */);
+ if(!result.isEmpty()) {
+ value = result;
+ }
+ }
+ value = Data::Image::idClean(value);
+ entry->setField(field->name(), value);
+ }
+ }
+ }
+ return true;
+}
+
+StateHandler* FieldsHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if((d->syntaxVersion > 3 && localName_ == Latin1Literal("field")) ||
+ (d->syntaxVersion < 4 && localName_ == Latin1Literal("attribute"))) {
+ return new FieldHandler(d);
+ }
+ return 0;
+}
+
+bool FieldsHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ d->defaultFields = false;
+ return true;
+}
+
+bool FieldsHandler::end(const TQString&, const TQString&, const TQString&) {
+ // add default fields if there was a default field name, or no names at all
+ const bool addFields = d->defaultFields || d->fields.isEmpty();
+ // in syntax 4, the element name was changed to "entry", always, rather than depending on
+ // on the entryName of the collection.
+ if(d->syntaxVersion > 3) {
+ d->entryName = TQString::fromLatin1("entry");
+ Data::Collection::Type type = static_cast<Data::Collection::Type>(d->collType);
+ d->coll = CollectionFactory::collection(type, addFields);
+ } else {
+ d->coll = CollectionFactory::collection(d->entryName, addFields);
+ }
+
+ if(!d->collTitle.isEmpty()) {
+ d->coll->setTitle(d->collTitle);
+ }
+
+ d->coll->addFields(d->fields);
+
+// as a special case, for old book collections with a bibtex-id field, convert to Bibtex
+ if(d->syntaxVersion < 4 && d->collType == Data::Collection::Book
+ && d->coll->hasField(TQString::fromLatin1("bibtex-id"))) {
+ d->coll = Data::BibtexCollection::convertBookCollection(d->coll);
+ }
+
+ return true;
+}
+
+StateHandler* FieldHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("prop")) {
+ return new FieldPropertyHandler(d);
+ }
+ return 0;
+}
+
+bool FieldHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ // special case: if the i18n attribute equals true, then translate the title, description, and category
+ const bool isI18n = attValue(atts_, "i18n") == Latin1Literal("true");
+
+ TQString name = attValue(atts_, "name", "unknown");
+ if(name == Latin1Literal("_default")) {
+ d->defaultFields = true;
+ return true;
+ }
+
+ TQString title = attValue(atts_, "title", i18n("Unknown"));
+ if(isI18n) {
+ title = i18n(title.utf8());
+ }
+
+ TQString typeStr = attValue(atts_, "type", TQString::number(Data::Field::Line));
+ Data::Field::Type type = static_cast<Data::Field::Type>(typeStr.toInt());
+
+ Data::FieldPtr field;
+ if(type == Data::Field::Choice) {
+ TQStringList allowed = TQStringList::split(TQRegExp(TQString::fromLatin1("\\s*;\\s*")),
+ attValue(atts_, "allowed"));
+ if(isI18n) {
+ for(TQStringList::Iterator word = allowed.begin(); word != allowed.end(); ++word) {
+ (*word) = i18n((*word).utf8());
+ }
+ }
+ field = new Data::Field(name, title, allowed);
+ } else {
+ field = new Data::Field(name, title, type);
+ }
+
+ int idx = atts_.index(TQString::fromLatin1("category"));
+ if(idx > -1) {
+ // at one point, the categories had keyboard accels
+ TQString cat = atts_.value(idx);
+ if(d->syntaxVersion < 9 && cat.find('&') > -1) {
+ cat.remove('&');
+ }
+ if(isI18n) {
+ cat = i18n(cat.utf8());
+ }
+ field->setCategory(cat);
+ }
+
+ idx = atts_.index(TQString::fromLatin1("flags"));
+ if(idx > -1) {
+ int flags = atts_.value(idx).toInt();
+ // I also changed the enum values for syntax 3, but the only custom field
+ // would have been bibtex-id
+ if(d->syntaxVersion < 3 && name == Latin1Literal("bibtex-id")) {
+ flags = 0;
+ }
+
+ // in syntax version 4, added a flag to disallow deleting attributes
+ // if it's a version before that and is the title, then add the flag
+ if(d->syntaxVersion < 4 && name == Latin1Literal("title")) {
+ flags |= Data::Field::NoDelete;
+ }
+ field->setFlags(flags);
+ }
+
+ TQString formatStr = attValue(atts_, "format", TQString::number(Data::Field::FormatNone));
+ Data::Field::FormatFlag format = static_cast<Data::Field::FormatFlag>(formatStr.toInt());
+ field->setFormatFlag(format);
+
+ idx = atts_.index(TQString::fromLatin1("description"));
+ if(idx > -1) {
+ TQString desc = atts_.value(idx);
+ if(isI18n) {
+ desc = i18n(desc.utf8());
+ }
+ field->setDescription(desc);
+ }
+
+ if(d->syntaxVersion < 5 && atts_.index(TQString::fromLatin1("bibtex-field")) > -1) {
+ field->setProperty(TQString::fromLatin1("bibtex"), attValue(atts_, "bibtex-field"));
+ }
+
+ // Table2 is deprecated
+ if(type == Data::Field::Table2) {
+ field->setType(Data::Field::Table);
+ field->setProperty(TQString::fromLatin1("columns"), TQChar('2'));
+ }
+
+ // for syntax 8, rating fields got their own type
+ if(d->syntaxVersion < 8) {
+ Data::Field::convertOldRating(field); // does all its own checking
+ }
+ d->fields.append(field);
+
+ return true;
+}
+
+bool FieldHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+bool FieldPropertyHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ // there should be at least one field already so we can add properties to it
+ Q_ASSERT(!d->fields.isEmpty());
+ Data::FieldPtr field = d->fields.back();
+
+ m_propertyName = attValue(atts_, "name");
+
+ // all track fields in music collections prior to version 9 get converted to three columns
+ if(d->syntaxVersion < 9) {
+ if(d->collType == Data::Collection::Album && field->name() == Latin1Literal("track")) {
+ field->setProperty(TQString::fromLatin1("columns"), TQChar('3'));
+ field->setProperty(TQString::fromLatin1("column1"), i18n("Title"));
+ field->setProperty(TQString::fromLatin1("column2"), i18n("Artist"));
+ field->setProperty(TQString::fromLatin1("column3"), i18n("Length"));
+ } else if(d->collType == Data::Collection::Video && field->name() == Latin1Literal("cast")) {
+ field->setProperty(TQString::fromLatin1("column1"), i18n("Actor/Actress"));
+ field->setProperty(TQString::fromLatin1("column2"), i18n("Role"));
+ }
+ }
+
+ return true;
+}
+
+bool FieldPropertyHandler::end(const TQString&, const TQString&, const TQString&) {
+ Q_ASSERT(!m_propertyName.isEmpty());
+ // add the previous property
+ Data::FieldPtr field = d->fields.back();
+ field->setProperty(m_propertyName, d->text);
+ return true;
+}
+
+bool BibtexPreambleHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool BibtexPreambleHandler::end(const TQString&, const TQString&, const TQString&) {
+ Q_ASSERT(d->coll);
+ if(d->coll && d->collType == Data::Collection::Bibtex && !d->text.isEmpty()) {
+ Data::BibtexCollection* c = static_cast<Data::BibtexCollection*>(d->coll.data());
+ c->setPreamble(d->text);
+ }
+ return true;
+}
+
+StateHandler* BibtexMacrosHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("macro")) {
+ return new BibtexMacroHandler(d);
+ }
+ return 0;
+}
+
+bool BibtexMacrosHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool BibtexMacrosHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+bool BibtexMacroHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ m_macroName = attValue(atts_, "name");
+ return true;
+}
+
+bool BibtexMacroHandler::end(const TQString&, const TQString&, const TQString&) {
+ if(d->coll && d->collType == Data::Collection::Bibtex && !m_macroName.isEmpty() && !d->text.isEmpty()) {
+ Data::BibtexCollection* c = static_cast<Data::BibtexCollection*>(d->coll.data());
+ c->addMacro(m_macroName, d->text);
+ }
+ return true;
+}
+
+StateHandler* EntryHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(d->coll->hasField(localName_)) {
+ return new FieldValueHandler(d);
+ }
+ return new FieldValueContainerHandler(d);
+}
+
+bool EntryHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ // the entries must come after the fields
+ if(!d->coll || d->coll->fields().isEmpty()) {
+ myWarning() << "EntryHandler::start() - entries must come after fields are defined" << endl;
+ // TODO: i18n
+ d->error = TQString::fromLatin1("File format error: entries must come after fields are defined");
+ return false;
+ }
+ int id = attValue(atts_, "id").toInt();
+ Data::EntryPtr entry;
+ if(id > 0) {
+ entry = new Data::Entry(d->coll, id);
+ } else {
+ entry = new Data::Entry(d->coll);
+ }
+ d->entries.append(entry);
+ return true;
+}
+
+bool EntryHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* FieldValueContainerHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(d->coll->hasField(localName_)) {
+ return new FieldValueHandler(d);
+ }
+ return new FieldValueContainerHandler(d);
+}
+
+bool FieldValueContainerHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool FieldValueContainerHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* FieldValueHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("year") ||
+ localName_ == Latin1Literal("month") ||
+ localName_ == Latin1Literal("day")) {
+ return new DateValueHandler(d);
+ } else if(localName_ == Latin1Literal("column")) {
+ return new TableColumnHandler(d);
+ }
+ return 0;
+}
+
+bool FieldValueHandler::start(const TQString&, const TQString&, const TQString& localName_, const TQXmlAttributes& atts_) {
+ d->currentField = d->coll->fieldByName(localName_);
+ m_i18n = attValue(atts_, "i18n") == Latin1Literal("true");
+ m_validateISBN = attValue(atts_, "validate") != Latin1Literal("no");
+ return true;
+}
+
+bool FieldValueHandler::end(const TQString&, const TQString& localName_, const TQString&) {
+ Data::FieldPtr f = d->coll->fieldByName(localName_);
+ if(!f) {
+ myWarning() << "FieldValueHandler::end() - no field named " << localName_ << endl;
+ return true;
+ }
+ // if it's a derived value, no field value is added
+ if(f->type() == Data::Field::Dependent) {
+ return true;
+ }
+
+ Data::EntryPtr entry = d->entries.back();
+ Q_ASSERT(entry);
+ TQString fieldName = localName_;
+ TQString fieldValue = d->text;
+
+ if(d->syntaxVersion < 2 && fieldName == Latin1Literal("keywords")) {
+ // in version 2, "keywords" changed to "keyword"
+ fieldName = TQString::fromLatin1("keyword");
+ } else if(d->syntaxVersion < 4 && f->type() == Data::Field::Bool) {
+ // in version 3 and prior, checkbox attributes had no text(), set it to "true"
+ fieldValue = TQString::fromLatin1("true");
+ } else if(d->syntaxVersion < 8 && f->type() == Data::Field::Rating) {
+ // in version 8, old rating fields get changed
+ bool ok;
+ uint i = Tellico::toUInt(fieldValue, &ok);
+ if(ok) {
+ fieldValue = TQString::number(i);
+ }
+ } else if(!d->textBuffer.isEmpty()) {
+ // for dates and tables, the value is built up from child elements
+#ifndef NDEBUG
+ if(!d->text.isEmpty()) {
+ myWarning() << "FieldValueHandler::end() - ignoring value for field " << localName_ << ": " << d->text << endl;
+ }
+#endif
+ fieldValue = d->textBuffer;
+ d->textBuffer = TQString();
+ }
+ // this is not an else branch, the data may be in the textBuffer
+ if(d->syntaxVersion < 9 && d->coll->type() == Data::Collection::Album && fieldName == Latin1Literal("track")) {
+ // yes, this assumes the artist has already been set
+ fieldValue += TQString::fromLatin1("::");
+ fieldValue += entry->field(TQString::fromLatin1("artist"));
+ }
+ // special case: if the i18n attribute equals true, then translate the title, description, and category
+ if(m_i18n) {
+ fieldValue = i18n(fieldValue.utf8());
+ }
+ // special case for isbn fields, go ahead and validate
+ if(m_validateISBN && fieldName == Latin1Literal("isbn")) {
+ ISBNValidator val(0);
+ val.fixup(fieldValue);
+ }
+ if(fieldValue.isEmpty()) {
+ return true;
+ }
+ // for fields with multiple values, we need to add on the new value
+ TQString oldValue = entry->field(fieldName);
+ if(!oldValue.isEmpty()) {
+ fieldValue = oldValue + TQString::fromLatin1("; ") + fieldValue;
+ }
+ entry->setField(fieldName, fieldValue);
+ return true;
+}
+
+bool DateValueHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool DateValueHandler::end(const TQString&, const TQString& localName_, const TQString&) {
+ // the data value is y-m-d even if there are no date values
+ if(d->textBuffer.isEmpty()) {
+ d->textBuffer = TQString::fromLatin1("--");
+ }
+ TQStringList tokens = TQStringList::split('-', d->textBuffer, true /* allow empty */);
+ Q_ASSERT(tokens.size() == 3);
+ if(localName_ == Latin1Literal("year")) {
+ tokens[0] = d->text;
+ } else if(localName_ == Latin1Literal("month")) {
+ tokens[1] = d->text;
+ } else if(localName_ == Latin1Literal("day")) {
+ tokens[2] = d->text;
+ }
+ d->textBuffer = tokens.join(TQChar('-'));
+ return true;
+}
+
+bool TableColumnHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool TableColumnHandler::end(const TQString&, const TQString&, const TQString&) {
+ // for old collections, if the second column holds the track length, bump it to next column
+ if(d->syntaxVersion < 9 &&
+ d->coll->type() == Data::Collection::Album &&
+ d->currentField->name() == Latin1Literal("track") &&
+ !d->textBuffer.isEmpty() &&
+ d->textBuffer.contains(TQString::fromLatin1("::")) == 0) {
+ TQRegExp rx(TQString::fromLatin1("\\d+:\\d\\d"));
+ if(rx.exactMatch(d->text)) {
+ d->text += TQString::fromLatin1("::");
+ d->text += d->entries.back()->field(TQString::fromLatin1("artist"));
+ }
+ }
+
+ if(!d->textBuffer.isEmpty()) {
+ d->textBuffer += TQString::fromLatin1("::");
+ }
+ d->textBuffer += d->text;
+ return true;
+}
+
+StateHandler* ImagesHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("image")) {
+ return new ImageHandler(d);
+ }
+ return 0;
+}
+
+bool ImagesHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ // reset variable that gets updated in the image handler
+ d->hasImages = false;
+ return true;
+}
+
+bool ImagesHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+bool ImageHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ m_format = attValue(atts_, "format");
+ m_link = attValue(atts_, "link") == Latin1Literal("true");
+ // idClean() already calls shareString()
+ m_imageId = m_link ? shareString(attValue(atts_, "id"))
+ : Data::Image::idClean(attValue(atts_, "id"));
+ m_width = attValue(atts_, "width").toInt();
+ m_height = attValue(atts_, "height").toInt();
+ return true;
+}
+
+bool ImageHandler::end(const TQString&, const TQString&, const TQString&) {
+ bool readInfo = true;
+ if(d->loadImages) {
+ TQByteArray ba;
+ KCodecs::base64Decode(TQCString(d->text.latin1()), ba);
+ if(!ba.isEmpty()) {
+ TQString result = ImageFactory::addImage(ba, m_format, m_imageId);
+ if(result.isEmpty()) {
+ myDebug() << "TellicoImporter::readImage(XML) - null image for " << m_imageId << endl;
+ }
+ d->hasImages = true;
+ readInfo = false;
+ }
+ }
+ if(readInfo) {
+ // a width or height of 0 is ok here
+ Data::ImageInfo info(m_imageId, m_format.latin1(), m_width, m_height, m_link);
+ ImageFactory::cacheImageInfo(info);
+ }
+ return true;
+}
+
+StateHandler* FiltersHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("filter")) {
+ return new FilterHandler(d);
+ }
+ return 0;
+}
+
+bool FiltersHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool FiltersHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* FilterHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("rule")) {
+ return new FilterRuleHandler(d);
+ }
+ return 0;
+}
+
+bool FilterHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ d->filter = new Filter(Filter::MatchAny);
+ d->filter->setName(attValue(atts_, "name"));
+
+ if(attValue(atts_, "match") == Latin1Literal("all")) {
+ d->filter->setMatch(Filter::MatchAll);
+ }
+ return true;
+}
+
+bool FilterHandler::end(const TQString&, const TQString&, const TQString&) {
+ if(d->coll && !d->filter->isEmpty()) {
+ d->coll->addFilter(d->filter);
+ }
+ d->filter = FilterPtr();
+ return true;
+}
+
+bool FilterRuleHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ TQString field = attValue(atts_, "field");
+ // empty field means match any of them
+ TQString pattern = attValue(atts_, "pattern");
+ // empty pattern is bad
+ if(pattern.isEmpty()) {
+ myWarning() << "FilterRuleHandler::start() - empty rule!" << endl;
+ return true;
+ }
+ TQString function = attValue(atts_, "function").lower();
+ FilterRule::Function func;
+ if(function == Latin1Literal("contains")) {
+ func = FilterRule::FuncContains;
+ } else if(function == Latin1Literal("notcontains")) {
+ func = FilterRule::FuncNotContains;
+ } else if(function == Latin1Literal("equals")) {
+ func = FilterRule::FuncEquals;
+ } else if(function == Latin1Literal("notequals")) {
+ func = FilterRule::FuncNotEquals;
+ } else if(function == Latin1Literal("regexp")) {
+ func = FilterRule::FuncRegExp;
+ } else if(function == Latin1Literal("notregexp")) {
+ func = FilterRule::FuncNotRegExp;
+ } else {
+ myWarning() << "FilterRuleHandler::start() - invalid rule function: " << function << endl;
+ return true;
+ }
+ d->filter->append(new FilterRule(field, pattern, func));
+ return true;
+}
+
+bool FilterRuleHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* BorrowersHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("borrower")) {
+ return new BorrowerHandler(d);
+ }
+ return 0;
+}
+
+bool BorrowersHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool BorrowersHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* BorrowerHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("loan")) {
+ return new LoanHandler(d);
+ }
+ return 0;
+}
+
+bool BorrowerHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ TQString name = attValue(atts_, "name");
+ TQString uid = attValue(atts_, "uid");
+ d->borrower = new Data::Borrower(name, uid);
+
+ return true;
+}
+
+bool BorrowerHandler::end(const TQString&, const TQString&, const TQString&) {
+ if(d->coll && !d->borrower->isEmpty()) {
+ d->coll->addBorrower(d->borrower);
+ }
+ d->borrower = Data::BorrowerPtr();
+ return true;
+}
+
+bool LoanHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ m_id = attValue(atts_, "entryRef").toInt();
+ m_uid = attValue(atts_, "uid");
+ m_loanDate = attValue(atts_, "loanDate");
+ m_dueDate = attValue(atts_, "dueDate");
+ m_inCalendar = attValue(atts_, "calendar") == Latin1Literal("true");
+ return true;
+}
+
+bool LoanHandler::end(const TQString&, const TQString&, const TQString&) {
+ Data::EntryPtr entry = d->coll->entryById(m_id);
+ if(!entry) {
+ myWarning() << "LoanHandler::end() - no entry with id = " << m_id << endl;
+ return true;
+ }
+ TQDate loanDate, dueDate;
+ if(!m_loanDate.isEmpty()) {
+ loanDate = TQDate::fromString(m_loanDate, TQt::ISODate);
+ }
+ if(!m_dueDate.isEmpty()) {
+ dueDate = TQDate::fromString(m_dueDate, TQt::ISODate);
+ }
+
+ Data::LoanPtr loan = new Data::Loan(entry, loanDate, dueDate, d->text);
+ loan->setUID(m_uid);
+ loan->setInCalendar(m_inCalendar);
+ d->borrower->addLoan(loan);
+ return true;
+}
+
diff --git a/src/translators/xmlstatehandler.h b/src/translators/xmlstatehandler.h
new file mode 100644
index 0000000..8b5c137
--- /dev/null
+++ b/src/translators/xmlstatehandler.h
@@ -0,0 +1,345 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef TELLICO_IMPORT_XMLSTATEHANDLER_H
+#define TELLICO_IMPORT_XMLSTATEHANDLER_H
+
+#ifdef QT_NO_CAST_ASCII
+#define HAD_QT_NO_CAST_ASCII
+#undef QT_NO_CAST_ASCII
+#endif
+
+#include <tqxml.h>
+
+#ifdef HAD_QT_NO_CAST_ASCII
+#define QT_NO_CAST_ASCII
+#undef HAD_QT_NO_CAST_ASCII
+#endif
+
+#include "../datavectors.h"
+
+namespace Tellico {
+ namespace Import {
+ namespace SAX {
+
+class StateData {
+public:
+ TQString text;
+ TQString error;
+ TQString ns; // namespace
+ TQString textBuffer;
+ uint syntaxVersion;
+ TQString collTitle;
+ int collType;
+ TQString entryName;
+ Data::CollPtr coll;
+ Data::FieldVec fields;
+ Data::FieldPtr currentField;
+ Data::EntryVec entries;
+ FilterPtr filter;
+ Data::BorrowerPtr borrower;
+ bool defaultFields;
+ bool loadImages;
+ bool hasImages;
+};
+
+class StateHandler {
+public:
+ StateHandler(StateData* data) : d(data) {}
+ virtual ~StateHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) = 0;
+ virtual bool end(const TQString&, const TQString&, const TQString&) = 0;
+
+ StateHandler* nextHandler(const TQString&, const TQString&, const TQString&);
+protected:
+ StateData* d;
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&) { return 0; }
+};
+
+class NullHandler : public StateHandler {
+public:
+ NullHandler(StateData* data) : StateHandler(data) {}
+ virtual ~NullHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) { return true; }
+ virtual bool end(const TQString&, const TQString&, const TQString&) { return true; }
+};
+
+class RootHandler : public StateHandler {
+public:
+ RootHandler(StateData* data) : StateHandler(data) {}
+ virtual ~RootHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) { return true; }
+ virtual bool end(const TQString&, const TQString&, const TQString&) { return true; }
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class DocumentHandler : public StateHandler {
+public:
+ DocumentHandler(StateData* data) : StateHandler(data) {}
+ virtual ~DocumentHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class CollectionHandler : public StateHandler {
+public:
+ CollectionHandler(StateData* data) : StateHandler(data) {}
+ virtual ~CollectionHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FieldsHandler : public StateHandler {
+public:
+ FieldsHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FieldsHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FieldHandler : public StateHandler {
+public:
+ FieldHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FieldHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FieldPropertyHandler : public StateHandler {
+public:
+ FieldPropertyHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FieldPropertyHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ TQString m_propertyName;
+};
+
+class BibtexPreambleHandler : public StateHandler {
+public:
+ BibtexPreambleHandler(StateData* data) : StateHandler(data) {}
+ virtual ~BibtexPreambleHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+};
+
+class BibtexMacrosHandler : public StateHandler {
+public:
+ BibtexMacrosHandler(StateData* data) : StateHandler(data) {}
+ virtual ~BibtexMacrosHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class BibtexMacroHandler : public StateHandler {
+public:
+ BibtexMacroHandler(StateData* data) : StateHandler(data) {}
+ virtual ~BibtexMacroHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ TQString m_macroName;
+};
+
+class EntryHandler : public StateHandler {
+public:
+ EntryHandler(StateData* data) : StateHandler(data) {}
+ virtual ~EntryHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FieldValueContainerHandler : public StateHandler {
+public:
+ FieldValueContainerHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FieldValueContainerHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FieldValueHandler : public StateHandler {
+public:
+ FieldValueHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FieldValueHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+ bool m_i18n;
+ bool m_validateISBN;
+};
+
+class DateValueHandler : public StateHandler {
+public:
+ DateValueHandler(StateData* data) : StateHandler(data) {}
+ virtual ~DateValueHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+};
+
+class TableColumnHandler : public StateHandler {
+public:
+ TableColumnHandler(StateData* data) : StateHandler(data) {}
+ virtual ~TableColumnHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+};
+
+class ImagesHandler : public StateHandler {
+public:
+ ImagesHandler(StateData* data) : StateHandler(data) {}
+ virtual ~ImagesHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class ImageHandler : public StateHandler {
+public:
+ ImageHandler(StateData* data) : StateHandler(data) {}
+ virtual ~ImageHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ TQString m_format;
+ bool m_link;
+ TQString m_imageId;
+ int m_width;
+ int m_height;
+};
+
+class FiltersHandler : public StateHandler {
+public:
+ FiltersHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FiltersHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FilterHandler : public StateHandler {
+public:
+ FilterHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FilterHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FilterRuleHandler : public StateHandler {
+public:
+ FilterRuleHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FilterRuleHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+};
+
+class BorrowersHandler : public StateHandler {
+public:
+ BorrowersHandler(StateData* data) : StateHandler(data) {}
+ virtual ~BorrowersHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class BorrowerHandler : public StateHandler {
+public:
+ BorrowerHandler(StateData* data) : StateHandler(data) {}
+ virtual ~BorrowerHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class LoanHandler : public StateHandler {
+public:
+ LoanHandler(StateData* data) : StateHandler(data) {}
+ virtual ~LoanHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ int m_id;
+ TQString m_uid;
+ TQString m_loanDate;
+ TQString m_dueDate;
+ bool m_inCalendar;
+};
+
+ }
+ }
+}
+#endif
diff --git a/src/translators/xsltexporter.cpp b/src/translators/xsltexporter.cpp
index c08ee0f..b0642b3 100644
--- a/src/translators/xsltexporter.cpp
+++ b/src/translators/xsltexporter.cpp
@@ -18,6 +18,8 @@
#include <tdelocale.h>
#include <kurlrequester.h>
+#include <kuser.h>
+#include <tdeconfig.h>
#include <tqlabel.h>
#include <tqgroupbox.h>
@@ -49,6 +51,9 @@ bool XSLTExporter::exec() {
}
// XSLTHandler handler(FileHandler::readXMLFile(url));
XSLTHandler handler(u);
+ handler.addStringParam("date", TQDate::currentDate().toString(TQt::ISODate).latin1());
+ handler.addStringParam("time", TQTime::currentTime().toString(TQt::ISODate).latin1());
+ handler.addStringParam("user", KUser(KUser::UseRealUserID).loginName().latin1());
TellicoXMLExporter exporter;
exporter.setEntries(entries());
@@ -75,6 +80,25 @@ TQWidget* XSLTExporter::widget(TQWidget* parent_, const char* name_/*=0*/) {
m_URLRequester = new KURLRequester(box);
TQWhatsThis::add(m_URLRequester, i18n("Choose the XSLT file used to transform the Tellico XML data."));
+ TQString filter = i18n("*.xsl|XSL Files (*.xsl)") + TQChar('\n');
+ filter += i18n("*|All Files");
+ m_URLRequester->setFilter(filter);
+ m_URLRequester->setMode(static_cast<KFile::Mode>(KFile::File | KFile::ExistingOnly));
+ if(!m_xsltFile.isEmpty()) {
+ m_URLRequester->setURL(m_xsltFile);
+ }
+
l->addStretch(1);
return m_widget;
}
+
+void XSLTExporter::readOptions(TDEConfig* config_) {
+ TDEConfigGroup group(config_, TQString::fromLatin1("ExportOptions - %1").arg(formatString()));
+ m_xsltFile = group.readEntry("Last File", TQString());
+}
+
+void XSLTExporter::saveOptions(TDEConfig* config_) {
+ TDEConfigGroup group(config_, TQString::fromLatin1("ExportOptions - %1").arg(formatString()));
+ m_xsltFile = m_URLRequester->url();
+ group.writeEntry("Last File", m_xsltFile);
+}
diff --git a/src/translators/xsltexporter.h b/src/translators/xsltexporter.h
index b14afd3..8b808e5 100644
--- a/src/translators/xsltexporter.h
+++ b/src/translators/xsltexporter.h
@@ -34,9 +34,13 @@ public:
virtual TQWidget* widget(TQWidget* parent, const char* name=0);
+ virtual void readOptions(TDEConfig* cfg);
+ virtual void saveOptions(TDEConfig* cfg);
+
private:
TQWidget* m_widget;
KURLRequester* m_URLRequester;
+ TQString m_xsltFile;
};
} // end namespace