7#include "datetimeparser_p.h"
8#include "fb2extractor.h"
9#include "kfilemetadata_debug.h"
13#include <QXmlStreamReader>
21Fb2Extractor::Fb2Extractor(
QObject *parent)
28static const QString regularMimeType()
30 return QStringLiteral(
"application/x-fictionbook+xml");
33static const QString compressedMimeType()
35 return QStringLiteral(
"application/x-zip-compressed-fb2");
38static const QStringList supportedMimeTypes = {regularMimeType(), compressedMimeType()};
44 return supportedMimeTypes;
49 std::unique_ptr<QIODevice> device;
50 std::unique_ptr<KZip> zip;
53 device.reset(
new QFile(result->
inputUrl()));
59 zip.reset(
new KZip(result->
inputUrl()));
61 qCDebug(KFILEMETADATA_LOG) <<
"Failed to open" << zip->fileName() <<
"-" << zip->errorString();
65 const auto entries = zip->directory()->entries();
66 if (entries.count() != 1) {
70 const QString entryPath = entries.first();
71 if (!entryPath.
endsWith(QLatin1String(
".fb2"))) {
75 const auto *entry = zip->directory()->file(entryPath);
80 device.reset(entry->createDevice());
85 QXmlStreamReader xml(device.get());
87 bool inFictionBook =
false;
88 bool inDescription =
false;
89 bool inTitleInfo =
false;
90 bool inAuthor =
false;
91 bool inDocumentInfo =
false;
92 bool inPublishInfo =
false;
95 QString authorFirstName;
96 QString authorMiddleName;
97 QString authorLastName;
98 QString authorNickName;
100 while (!xml.atEnd() && !xml.hasError()) {
103 if (xml.name() == QLatin1String(
"FictionBook")) {
104 if (xml.isStartElement()) {
105 inFictionBook =
true;
106 }
else if (xml.isEndElement()) {
109 }
else if (xml.name() == QLatin1String(
"description")) {
110 if (xml.isStartElement()) {
111 inDescription =
true;
112 }
else if (xml.isEndElement()) {
113 inDescription =
false;
115 }
else if (xml.name() == QLatin1String(
"title-info")) {
116 if (xml.isStartElement()) {
118 }
else if (xml.isEndElement()) {
121 }
else if (xml.name() == QLatin1String(
"document-info")) {
122 if (xml.isStartElement()) {
123 inDocumentInfo =
true;
124 }
else if (xml.isEndElement()) {
125 inDocumentInfo =
false;
127 }
else if (xml.name() == QLatin1String(
"publish-info")) {
128 if (xml.isStartElement()) {
129 inPublishInfo =
true;
130 }
else if (xml.isEndElement()) {
131 inPublishInfo =
false;
133 }
else if (xml.name() == QLatin1String(
"body")) {
134 if (xml.isStartElement()) {
136 }
else if (xml.isEndElement()) {
141 if (!inFictionBook) {
145 if (inDescription && result->
inputFlags() & ExtractionResult::ExtractMetaData) {
147 if (xml.isStartElement()) {
148 if (xml.name() == QLatin1String(
"author")) {
150 }
else if (inAuthor) {
151 if (xml.name() == QLatin1String(
"first-name")) {
152 authorFirstName = xml.readElementText();
153 }
else if (xml.name() == QLatin1String(
"middle-name")) {
154 authorMiddleName = xml.readElementText();
155 }
else if (xml.name() == QLatin1String(
"last-name")) {
156 authorLastName = xml.readElementText();
157 }
else if (xml.name() == QLatin1String(
"nickname")) {
158 authorNickName = xml.readElementText();
160 }
else if (xml.name() == QLatin1String(
"book-title")) {
162 }
else if (xml.name() == QLatin1String(
"annotation")) {
164 }
else if (xml.name() == QLatin1String(
"lang")) {
166 }
else if (xml.name() == QLatin1String(
"genre")) {
169 }
else if (xml.isEndElement()) {
172 QStringList nameParts = {authorFirstName, authorMiddleName, authorLastName};
177 }
else if (!authorNickName.
isEmpty()) {
181 authorFirstName.
clear();
182 authorMiddleName.
clear();
183 authorLastName.
clear();
184 authorNickName.
clear();
186 }
else if (inDocumentInfo) {
187 if (xml.name() == QLatin1String(
"date")) {
189 const auto dateValue = xml.attributes().value(QLatin1String(
"value"));
193 dt = Parser::dateTimeFromString(xml.readElementText());
199 }
else if (xml.name() == QLatin1String(
"program-used")) {
202 }
else if (xml.name() == QLatin1String(
"publisher")) {
205 }
else if (inPublishInfo) {
206 if (xml.name() == QLatin1String(
"publisher")) {
208 }
else if (xml.name() == QLatin1String(
"year")) {
210 const int releaseYear = xml.readElementText().toInt(&ok);
216 }
else if (inBody && result->
inputFlags() & ExtractionResult::ExtractPlainText && xml.isCharacters() && !xml.isWhitespace()) {
217 result->
append(xml.text().toString());
222#include "moc_fb2extractor.cpp"
QDateTime fromString(QStringView string, QStringView format, QCalendar cal)
bool isValid() const const
bool isEmpty() const const
qsizetype removeAll(const AT &t)
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString join(QChar separator) const const