You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
114 lines
3.7 KiB
114 lines
3.7 KiB
/* |
|
SPDX-FileCopyrightText: 2008 Jakub Stachowski <qbast@go2.pl> |
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later |
|
*/ |
|
|
|
#include "converter.h" |
|
|
|
#include <QAbstractTextDocumentLayout> |
|
#include <QDebug> |
|
#include <QFile> |
|
#include <QTextBlock> |
|
#include <QTextDocument> |
|
#include <QTextDocumentFragment> |
|
#include <QTextFrame> |
|
|
|
#include <KLocalizedString> |
|
#include <core/action.h> |
|
|
|
using namespace Mobi; |
|
|
|
Converter::Converter() |
|
{ |
|
} |
|
|
|
Converter::~Converter() |
|
{ |
|
} |
|
|
|
void Converter::handleMetadata(const QMap<Mobipocket::Document::MetaKey, QString> &metadata) |
|
{ |
|
QMapIterator<Mobipocket::Document::MetaKey, QString> it(metadata); |
|
while (it.hasNext()) { |
|
it.next(); |
|
switch (it.key()) { |
|
case Mobipocket::Document::Title: |
|
emit addMetaData(Okular::DocumentInfo::Title, it.value()); |
|
break; |
|
case Mobipocket::Document::Author: |
|
emit addMetaData(Okular::DocumentInfo::Author, it.value()); |
|
break; |
|
case Mobipocket::Document::Description: |
|
emit addMetaData(Okular::DocumentInfo::Description, it.value()); |
|
break; |
|
case Mobipocket::Document::Subject: |
|
emit addMetaData(Okular::DocumentInfo::Subject, it.value()); |
|
break; |
|
case Mobipocket::Document::Copyright: |
|
emit addMetaData(Okular::DocumentInfo::Copyright, it.value()); |
|
break; |
|
} |
|
} |
|
} |
|
|
|
QTextDocument *Converter::convert(const QString &fileName) |
|
{ |
|
MobiDocument *newDocument = new MobiDocument(fileName); |
|
if (!newDocument->mobi()->isValid()) { |
|
emit error(i18n("Error while opening the Mobipocket document."), -1); |
|
delete newDocument; |
|
return nullptr; |
|
} |
|
if (newDocument->mobi()->hasDRM()) { |
|
emit error(i18n("This book is protected by DRM and can be displayed only on designated device"), -1); |
|
delete newDocument; |
|
return nullptr; |
|
} |
|
|
|
handleMetadata(newDocument->mobi()->metadata()); |
|
newDocument->setPageSize(QSizeF(600, 800)); |
|
|
|
QTextFrameFormat frameFormat; |
|
frameFormat.setMargin(20); |
|
QTextFrame *rootFrame = newDocument->rootFrame(); |
|
rootFrame->setFrameFormat(frameFormat); |
|
QMap<QString, QPair<int, int>> links; |
|
QMap<QString, QTextBlock> targets; |
|
|
|
// go over whole document and add all <a> 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<int, int>(frag.position(), frag.position() + frag.length()); |
|
const QStringList anchors = format.anchorNames(); |
|
if (!anchors.isEmpty()) { |
|
// link targets |
|
for (const QString &name : anchors) |
|
targets[QLatin1Char('#') + name] = it; |
|
} |
|
} |
|
|
|
// create link actions |
|
QMapIterator<QString, QPair<int, int>> it(links); |
|
while (it.hasNext()) { |
|
it.next(); |
|
QUrl u(it.key()); |
|
// external or internal link |
|
if (!u.isRelative()) |
|
emit addAction(new Okular::BrowseAction(QUrl(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; |
|
}
|
|
|