summaryrefslogtreecommitdiffstats
path: root/src/translators/tellicosaximporter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/translators/tellicosaximporter.cpp')
-rw-r--r--src/translators/tellicosaximporter.cpp293
1 files changed, 293 insertions, 0 deletions
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"