|
|
|
/***************************************************************************
|
|
|
|
copyright : (C) 2008 by Robby Stephenson
|
|
|
|
email : robby@periapsis.org
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
* *
|
|
|
|
* 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 TQT_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"
|