From d8ae4fd45819d8f7b1c564eaa8b7588c215e4551 Mon Sep 17 00:00:00 2001 From: Jakub Stachowski Date: Tue, 11 Nov 2008 22:08:26 +0000 Subject: [PATCH] Add support for links in document. Internal links are not completely reliable yet. svn path=/trunk/playground/graphics/okular/mobipocket/; revision=883025 --- converter.cpp | 38 +++++++++++++++++++++++++++++++++++++- mobidocument.cpp | 45 ++++++++++++++++++++++++++++++++++++--------- 2 files changed, 73 insertions(+), 10 deletions(-) diff --git a/converter.cpp b/converter.cpp index c95cff13a..9bd8a90ba 100644 --- a/converter.cpp +++ b/converter.cpp @@ -11,8 +11,9 @@ #include #include +#include #include -#include +#include #include #include #include @@ -67,5 +68,40 @@ QTextDocument* Converter::convert( const QString &fileName ) frameFormat.setMargin( 20 ); QTextFrame *rootFrame = newDocument->rootFrame(); rootFrame->setFrameFormat( frameFormat ); + QMap > links; + QMap targets; + + // go over whole document and add all tags to links or targets map + for (QTextBlock it = newDocument->begin(); it != newDocument->end(); it = it.next()) + for (QTextBlock::iterator fit=it.begin(); !fit.atEnd(); ++fit) { + QTextFragment frag=fit.fragment(); + QTextCharFormat format=frag.charFormat(); + if (!format.isAnchor()) continue; + //link + if (!format.anchorHref().isEmpty()) links[format.anchorHref()]= + QPair(frag.position(), frag.position()+frag.length()); + if (!format.anchorNames().isEmpty()) { + // link targets + Q_FOREACH(QString name, format.anchorNames()) + targets["#"+name]=it; + } + } + + // create link actions + QMapIterator > it(links); + while (it.hasNext()) { + it.next(); + QUrl u(it.key()); + // external or internal link + if (!u.isRelative()) emit addAction(new Okular::BrowseAction(it.key()), it.value().first, it.value().second); + else { + // is there valid target? + if (!targets.contains( it.key() ) || !targets[it.key()].isValid()) continue; + emit addAction(new Okular::GotoAction(QString(), calculateViewport( newDocument, targets[it.key()] )), + it.value().first, it.value().second); + } + + } + return newDocument; } diff --git a/mobidocument.cpp b/mobidocument.cpp index adce53e72..641b6367a 100644 --- a/mobidocument.cpp +++ b/mobidocument.cpp @@ -8,8 +8,8 @@ ***************************************************************************/ #include "mobidocument.h" #include "mobipocket.h" -#include -#include +#include +#include #include using namespace Mobi; @@ -30,13 +30,9 @@ MobiDocument::~MobiDocument() QVariant MobiDocument::loadResource(int type, const QUrl &name) { - - kDebug() << "Requested resource: " << type << " URL " << name; - if (type!=QTextDocument::ImageResource || name.scheme()!=QString("pdbrec")) return QVariant(); bool ok; quint16 recnum=name.path().mid(1).toUShort(&ok); - kDebug() << "Path" << name.path().mid(1) << " Img " << recnum << " all imgs " << doc->imageCount(); if (!ok || recnum>=doc->imageCount()) return QVariant(); QVariant resource; @@ -46,15 +42,46 @@ QVariant MobiDocument::loadResource(int type, const QUrl &name) 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]=='>') return pos; + if (data[i]=='<') return i; + } + return pos; +} QString MobiDocument::fixMobiMarkup(const QString& data) { - QRegExp imgs("<[iI][mM][gG].*recindex=\"([0-9]*)\".*>"); + static QRegExp imgs("", Qt::CaseInsensitive); imgs.setMinimal(true); QString ret=data; ret.replace(imgs,""); - ret.replace("","

"); - //FIXME: anchors + //ret.replace("","

"); + QMap anchorPositions; + static QRegExp anchors(" it(anchorPositions); + while (it.hasNext()) { + it.next(); + int fixedpos=outsideTag(ret, it.key()+offset); + ret.insert(fixedpos,QString("
")); + offset+=12+it.value().size(); + } + + // replace links referencing filepos with normal internal links + ret.replace(anchors,"