fix internal links

This commit is contained in:
Jaydeep Solanki 2013-10-22 05:33:17 +05:30 committed by Albert Astals Cid
parent c0cc3af9be
commit 6b3ac2e1b0
2 changed files with 57 additions and 15 deletions

View file

@ -13,6 +13,7 @@
#include <QtGui/QTextDocument>
#include <QtGui/QTextFrame>
#include <QTextDocumentFragment>
#include <QFileInfo>
#include <kdebug.h>
#include <klocale.h>
@ -62,9 +63,10 @@ void Converter::_emitData(Okular::DocumentInfo::Key key,
}
}
// Got over the blocks from start and add them to hashes use name as the
// Got over the blocks from start and add them to hashes use name as the
// prefix for local links
void Converter::_handle_anchors(const QTextBlock &start, const QString &name) {
const QString curDir = QFileInfo(name).path();
for (QTextBlock bit = start; bit != mTextDocument->end(); bit = bit.next()) {
for (QTextBlock::iterator fit = bit.begin(); !(fit.atEnd()); ++fit) {
@ -72,14 +74,35 @@ void Converter::_handle_anchors(const QTextBlock &start, const QString &name) {
QTextFragment frag = fit.fragment();
if (frag.isValid() && frag.charFormat().isAnchor()) {
QUrl href(frag.charFormat().anchorHref());
QString hrefString = frag.charFormat().anchorHref();
// remove ./ or ../
// making it easier to compare, with links
while(!hrefString.isNull() && ( hrefString.at(0) == '.' || hrefString.at(0) == '/') ){
hrefString.remove(0,1);
}
QUrl href(hrefString);
if (href.isValid() && !href.isEmpty()) {
if (href.isRelative()) { // Inside document link
mLocalLinks.insert(href.toString(),
QPair<int, int>(frag.position(),
frag.position()+frag.length()));
} else { // Outside document link
if(!hrefString.indexOf('#'))
hrefString = name + hrefString;
else if(QFileInfo(hrefString).path() == "." && curDir != ".")
hrefString = curDir + '/' + hrefString;
// QTextCharFormat sometimes splits a link in two
// if there's no white space between words & the first one is an anchor
// consider whole word to be an anchor
++fit;
int fragLen = frag.length();
if(!fit.atEnd() && ((fit.fragment().position() - frag.position()) == 1))
fragLen += fit.fragment().length();
--fit;
_insert_local_links(hrefString,
QPair<int, int>(frag.position(),
frag.position()+fragLen));
} else { // Outside document link
Okular::BrowseAction *action =
new Okular::BrowseAction(href.toString());
@ -101,6 +124,17 @@ void Converter::_handle_anchors(const QTextBlock &start, const QString &name) {
}
}
void Converter::_insert_local_links(const QString &key, const QPair<int, int> &value)
{
if(mLocalLinks.contains(key)){
mLocalLinks[key].append(value);
} else {
QVector< QPair<int, int> > vec;
vec.append(value);
mLocalLinks.insert(key,vec);
}
}
QTextDocument* Converter::convert( const QString &fileName )
{
EpubDocument *newDocument = new EpubDocument(fileName);
@ -142,6 +176,10 @@ QTextDocument* Converter::convert( const QString &fileName )
mTextDocument->setCurrentSubDocument(link);
QString htmlContent = QString::fromUtf8(epub_it_get_curr(it));
// as QTextCharFormat::anchorNames() ignores sections, replace it with <p>
htmlContent.replace(QRegExp("< *section"),"<p");
htmlContent.replace(QRegExp("< */ *section"),"</p");
QTextBlock before;
if(firstPage) {
// preHtml & postHtml make it possible to have a margin around the content of the page
@ -243,20 +281,23 @@ QTextDocument* Converter::convert( const QString &fileName )
}
// adding link actions
QHashIterator<QString, QPair<int, int> > hit(mLocalLinks);
QHashIterator<QString, QVector< QPair<int, int> > > hit(mLocalLinks);
while (hit.hasNext()) {
hit.next();
const QTextBlock block = mSectionMap.value(hit.key());
if (block.isValid()) { // be sure we actually got a block
Okular::DocumentViewport viewport =
calculateViewport(mTextDocument, block);
Okular::GotoAction *action = new Okular::GotoAction(QString(), viewport);
for (int i = 0; i < hit.value().size(); ++i) {
if (block.isValid()) { // be sure we actually got a block
Okular::DocumentViewport viewport =
calculateViewport(mTextDocument, block);
emit addAction(action, hit.value().first, hit.value().second);
} else {
kDebug() << "Error: no block found for "<< hit.key();
Okular::GotoAction *action = new Okular::GotoAction(QString(), viewport);
emit addAction(action, hit.value()[i].first, hit.value()[i].second);
} else {
kDebug() << "Error: no block found for "<< hit.key();
}
}
}

View file

@ -30,10 +30,11 @@ namespace Epub {
void _emitData(Okular::DocumentInfo::Key key, enum epub_metadata type);
void _handle_anchors(const QTextBlock &start, const QString &name);
void _insert_local_links(const QString &key, const QPair<int, int> &value);
EpubDocument *mTextDocument;
QHash<QString, QTextBlock> mSectionMap;
QHash<QString, QPair<int, int> > mLocalLinks;
QHash<QString, QVector< QPair<int, int> > > mLocalLinks;
};
}