File indexing completed on 2024-05-12 04:34:02
0001 /* 0002 SPDX-FileCopyrightText: 2008 Jakub Stachowski <qbast@go2.pl> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "converter.h" 0008 0009 #include <QAbstractTextDocumentLayout> 0010 #include <QDebug> 0011 #include <QFile> 0012 #include <QTextBlock> 0013 #include <QTextDocument> 0014 #include <QTextDocumentFragment> 0015 #include <QTextFrame> 0016 0017 #include <KLocalizedString> 0018 #include <core/action.h> 0019 0020 using namespace Mobi; 0021 0022 Converter::Converter() 0023 { 0024 } 0025 0026 Converter::~Converter() 0027 { 0028 } 0029 0030 void Converter::handleMetadata(const QMap<Mobipocket::Document::MetaKey, QString> &metadata) 0031 { 0032 QMapIterator<Mobipocket::Document::MetaKey, QString> it(metadata); 0033 while (it.hasNext()) { 0034 it.next(); 0035 switch (it.key()) { 0036 case Mobipocket::Document::Title: 0037 Q_EMIT addMetaData(Okular::DocumentInfo::Title, it.value()); 0038 break; 0039 case Mobipocket::Document::Author: 0040 Q_EMIT addMetaData(Okular::DocumentInfo::Author, it.value()); 0041 break; 0042 case Mobipocket::Document::Description: 0043 Q_EMIT addMetaData(Okular::DocumentInfo::Description, it.value()); 0044 break; 0045 case Mobipocket::Document::Subject: 0046 Q_EMIT addMetaData(Okular::DocumentInfo::Subject, it.value()); 0047 break; 0048 case Mobipocket::Document::Copyright: 0049 Q_EMIT addMetaData(Okular::DocumentInfo::Copyright, it.value()); 0050 break; 0051 } 0052 } 0053 } 0054 0055 QTextDocument *Converter::convert(const QString &fileName) 0056 { 0057 MobiDocument *newDocument = new MobiDocument(fileName); 0058 if (!newDocument->mobi()->isValid()) { 0059 Q_EMIT error(i18n("Error while opening the Mobipocket document."), -1); 0060 delete newDocument; 0061 return nullptr; 0062 } 0063 if (newDocument->mobi()->hasDRM()) { 0064 Q_EMIT error(i18n("This book is protected by DRM and can be displayed only on designated device"), -1); 0065 delete newDocument; 0066 return nullptr; 0067 } 0068 0069 handleMetadata(newDocument->mobi()->metadata()); 0070 newDocument->setPageSize(QSizeF(600, 800)); 0071 0072 QTextFrameFormat frameFormat; 0073 frameFormat.setMargin(20); 0074 QTextFrame *rootFrame = newDocument->rootFrame(); 0075 rootFrame->setFrameFormat(frameFormat); 0076 QMap<QString, QPair<int, int>> links; 0077 QMap<QString, QTextBlock> targets; 0078 0079 // go over whole document and add all <a> tags to links or targets map 0080 for (QTextBlock it = newDocument->begin(); it != newDocument->end(); it = it.next()) { 0081 for (QTextBlock::iterator fit = it.begin(); !fit.atEnd(); ++fit) { 0082 QTextFragment frag = fit.fragment(); 0083 QTextCharFormat format = frag.charFormat(); 0084 if (!format.isAnchor()) { 0085 continue; 0086 } 0087 // link 0088 if (!format.anchorHref().isEmpty()) { 0089 links[format.anchorHref()] = QPair<int, int>(frag.position(), frag.position() + frag.length()); 0090 } 0091 const QStringList anchors = format.anchorNames(); 0092 if (!anchors.isEmpty()) { 0093 // link targets 0094 for (const QString &name : anchors) { 0095 targets[QLatin1Char('#') + name] = it; 0096 } 0097 } 0098 } 0099 } 0100 0101 // create link actions 0102 QMapIterator<QString, QPair<int, int>> it(links); 0103 while (it.hasNext()) { 0104 it.next(); 0105 QUrl u(it.key()); 0106 // external or internal link 0107 if (!u.isRelative()) { 0108 Q_EMIT addAction(new Okular::BrowseAction(QUrl(it.key())), it.value().first, it.value().second); 0109 } else { 0110 // is there valid target? 0111 if (!targets.contains(it.key()) || !targets[it.key()].isValid()) { 0112 continue; 0113 } 0114 Q_EMIT addAction(new Okular::GotoAction(QString(), calculateViewport(newDocument, targets[it.key()])), it.value().first, it.value().second); 0115 } 0116 } 0117 0118 return newDocument; 0119 }