/*************************************************************************** * Copyright (C) 2008 by Jakub Stachowski * * * * 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. * ***************************************************************************/ #include "mobidocument.h" #include // Because of the HACK #include #include #include #include // Because of the HACK #include #include #include using namespace Mobi; MobiDocument::MobiDocument(const QString &fileName) : QTextDocument() { file = new Mobipocket::QFileStream(fileName); doc = new Mobipocket::Document(file); if (doc->isValid()) { QString text = doc->text(); QString header = text.left(1024); if (header.contains(QStringLiteral("")) || header.contains(QStringLiteral(""))) { // HACK BEGIN Get the links without CSS to be blue // Remove if Qt ever gets fixed and the code in textdocumentgenerator.cpp works const QPalette orig = qApp->palette(); QPalette p = orig; p.setColor(QPalette::Link, Qt::blue); qApp->setPalette(p); // HACK END setHtml(fixMobiMarkup(text)); // HACK BEGIN qApp->setPalette(orig); // HACK END } else { setPlainText(text); } } } MobiDocument::~MobiDocument() { delete doc; delete file; } QVariant MobiDocument::loadResource(int type, const QUrl &name) { if (type != QTextDocument::ImageResource || name.scheme() != QString(QStringLiteral("pdbrec"))) return QVariant(); bool ok; quint16 recnum = name.path().midRef(1).toUShort(&ok); if (!ok || recnum >= doc->imageCount()) return QVariant(); QVariant resource; resource.setValue(doc->getImage(recnum - 1)); addResource(type, name, resource); return resource; } // starting from 'pos', find position in the string that is not inside a tag int outsideTag(const QString &data, int pos) { for (int i = pos - 1; i >= 0; i--) { if (data[i] == QLatin1Char('>')) return pos; if (data[i] == QLatin1Char('<')) return i; } return pos; } QString MobiDocument::fixMobiMarkup(const QString &data) { QString ret = data; QMap anchorPositions; static QRegExp anchors(QStringLiteral(" it(anchorPositions); while (it.hasNext()) { it.next(); // link pointing outside the document, ignore if ((it.key() + offset) >= ret.size()) continue; int fixedpos = outsideTag(ret, it.key() + offset); ret.insert(fixedpos, QStringLiteral(" ")); // inserting anchor shifts all offsets after the anchor offset += 21 + it.value().size(); } // replace links referencing filepos with normal internal links ret.replace(anchors, QStringLiteral(" where recindex is number of // record containing image static QRegExp imgs(QStringLiteral(""), Qt::CaseInsensitive); imgs.setMinimal(true); ret.replace(imgs, QStringLiteral("")); ret.replace(QStringLiteral(""), QStringLiteral("

")); return ret; }