[office/tellico] /: Import metadata from EPub, FB2, and Mobi ebook formats
Robby Stephenson
null at kde.org
Fri Mar 10 02:41:30 GMT 2023
Git commit c7e7eb08c431163733cfac23be594d9ee53c7524 by Robby Stephenson.
Committed on 10/03/2023 at 02:41.
Pushed by rstephenson into branch 'master'.
Import metadata from EPub, FB2, and Mobi ebook formats
Importing is supported for drag-and-drop, subject to support from
KFileMetadata. Combining with PDF import isn't supported yet.
BUG: 450192
FIXED-IN: 3.5
M +4 -0 ChangeLog
M +1 -1 doc/importing-exporting.docbook
M +10 -3 src/gui/drophandler.cpp
M +10 -0 src/importdialog.cpp
M +1 -0 src/translators/CMakeLists.txt
A +136 -0 src/translators/ebookimporter.cpp [License: GPL (v2/3)]
C +34 -68 src/translators/ebookimporter.h [from: src/translators/translators.h - 063% similarity]
M +2 -1 src/translators/translators.h
https://invent.kde.org/office/tellico/commit/c7e7eb08c431163733cfac23be594d9ee53c7524
diff --git a/ChangeLog b/ChangeLog
index 167838cc..c5866af1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2023-03-09 Robby Stephenson <robby at periapsis.org>
+
+ * Added support for importing EPub data on drag/drop (Bug 450192).
+
2023-02-20 Robby Stephenson <robby at periapsis.org>
* Updated AMS MR Lookup data source.
diff --git a/doc/importing-exporting.docbook b/doc/importing-exporting.docbook
index 753815da..249470af 100644
--- a/doc/importing-exporting.docbook
+++ b/doc/importing-exporting.docbook
@@ -222,7 +222,7 @@ Any &XML; file may be imported into &appname; provided an &XSL; stylesheet is av
<sect1 id="drag-n-drop">
<title>Drag and Drop</title>
-<para>Dragging data files to the main &appname; window and dropping them will import the files, just as if the <link linkend="importing">import command</link> was made from the menus. Drag and drop works for the following file formats: Tellico, Bibtex, RIS, and &PDF;. Importing multiple files at once is also supported.</para>
+<para>Dragging data files to the main &appname; window and dropping them will import the files, just as if the <link linkend="importing">import command</link> was made from the menus. Drag and drop works for the following file formats: Tellico, Bibtex, RIS, &PDF;, and EPub. Importing multiple files at once is also supported.</para>
<para>So, for example, if you want to catalog several <link linkend="importing-pdf">&PDF; files</link>, select them in the file manager and drag them to the &appname; window. &appname; will import as much metadata from the files as it can, and then fetch additional information from various configured Internet sources.</para>
diff --git a/src/gui/drophandler.cpp b/src/gui/drophandler.cpp
index 8bac7b03..3bf5cc77 100644
--- a/src/gui/drophandler.cpp
+++ b/src/gui/drophandler.cpp
@@ -84,19 +84,18 @@ bool DropHandler::drop(QDropEvent* event_) {
bool DropHandler::handleURL(const QList<QUrl>& urls_) {
bool hasUnknown = false;
- QList<QUrl> tc, pdf, bib, ris, ciw;
+ QMimeDatabase db;
+ QList<QUrl> tc, pdf, bib, ris, ciw, ebook;
foreach(const QUrl& url, urls_) {
QMimeType ptr;
// findByURL doesn't work for http, so actually query
// the url itself
if(url.scheme() != QLatin1String("http")) {
- QMimeDatabase db;
ptr = db.mimeTypeForUrl(url);
} else {
KIO::MimetypeJob* job = KIO::mimetype(url, KIO::HideProgressInfo);
KJobWidgets::setWindow(job, GUI::Proxy::widget());
job->exec();
- QMimeDatabase db;
ptr = db.mimeTypeForName(job->mimetype());
}
if(ptr.inherits(QStringLiteral("application/x-tellico"))) {
@@ -109,6 +108,11 @@ bool DropHandler::handleURL(const QList<QUrl>& urls_) {
bib << url;
} else if(ptr.inherits(QStringLiteral("application/x-research-info-systems"))) {
ris << url;
+ } else if(ptr.inherits(QStringLiteral("application/epub+zip")) ||
+ ptr.inherits(QStringLiteral("application/x-mobipocket-ebook")) ||
+ ptr.inherits(QStringLiteral("application/x-fictionbook+xml")) ||
+ ptr.inherits(QStringLiteral("application/x-zip-compressed-fb2"))) {
+ ebook << url;
} else if(url.fileName().endsWith(QLatin1String(".bib"))) {
bib << url;
} else if(url.fileName().endsWith(QLatin1String(".ris"))) {
@@ -146,6 +150,9 @@ bool DropHandler::handleURL(const QList<QUrl>& urls_) {
if(!ciw.isEmpty()) {
mainWindow->importFile(Import::CIW, ciw);
}
+ if(!ebook.isEmpty()) {
+ mainWindow->importFile(Import::EBook, ebook);
+ }
// any unknown urls get passed
return !hasUnknown;
}
diff --git a/src/importdialog.cpp b/src/importdialog.cpp
index 408d2dda..c4b22525 100644
--- a/src/importdialog.cpp
+++ b/src/importdialog.cpp
@@ -55,6 +55,7 @@
#include "translators/collectorzimporter.h"
#include "translators/datacrowimporter.h"
#include "translators/marcimporter.h"
+#include "translators/ebookimporter.h"
#include "utils/datafileregistry.h"
#include <KLocalizedString>
@@ -328,6 +329,10 @@ Tellico::Import::Importer* ImportDialog::importer(Tellico::Import::Format format
CHECK_SIZE;
importer = new Import::MarcImporter(firstURL);
break;
+
+ case Import::EBook:
+ importer = new Import::EBookImporter(urls_);
+ break;
}
if(!importer) {
myWarning() << "importer not created!";
@@ -414,6 +419,11 @@ QString ImportDialog::fileFilter(Tellico::Import::Format format_) {
text += i18n("XML Files") + QLatin1String(" (*.xml)") + QLatin1String(";;");
break;
+ case Import::EBook:
+ // KFileMetaData has extractors that support mimetypes with these typical extensions
+ text = i18n("eBook Files") + QLatin1String(" (*.epub *.fb2 *.fb2zip *.mobi)") + QLatin1String(";;");
+ break;
+
case Import::AudioFile:
case Import::Alexandria:
case Import::FreeDB:
diff --git a/src/translators/CMakeLists.txt b/src/translators/CMakeLists.txt
index 602b28f4..1d92c123 100644
--- a/src/translators/CMakeLists.txt
+++ b/src/translators/CMakeLists.txt
@@ -19,6 +19,7 @@ SET(translators_STAT_SRCS
datacrowimporter.cpp
dataimporter.cpp
deliciousimporter.cpp
+ ebookimporter.cpp
exporter.cpp
filelistingimporter.cpp
freedb_util.cpp
diff --git a/src/translators/ebookimporter.cpp b/src/translators/ebookimporter.cpp
new file mode 100644
index 00000000..b67a5d6b
--- /dev/null
+++ b/src/translators/ebookimporter.cpp
@@ -0,0 +1,136 @@
+/***************************************************************************
+ Copyright (C) 2023 Robby Stephenson <robby at periapsis.org>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU General Public License as *
+ * published by the Free Software Foundation; either version 2 of *
+ * the License or (at your option) version 3 or any later version *
+ * accepted by the membership of KDE e.V. (or its successor approved *
+ * by the membership of KDE e.V.), which shall act as a proxy *
+ * defined in Section 14 of version 3 of the license. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
+ * *
+ ***************************************************************************/
+
+#include <config.h>
+
+#include "ebookimporter.h"
+#include "../collections/bookcollection.h"
+#include "../core/netaccess.h"
+#include "../images/imagefactory.h"
+#include "../utils/datafileregistry.h"
+#include "../tellico_debug.h"
+
+#include <KLocalizedString>
+#include <KFileItem>
+#ifdef HAVE_KFILEMETADATA
+#include <KFileMetaData/Extractor>
+#include <KFileMetaData/ExtractorCollection>
+#include <KFileMetaData/SimpleExtractionResult>
+#include <KFileMetaData/PropertyInfo>
+#endif
+
+#include <QPixmap>
+
+using Tellico::Import::EBookImporter;
+
+EBookImporter::EBookImporter(const QUrl& url_) : Importer(url_) {
+}
+
+EBookImporter::EBookImporter(const QList<QUrl>& urls_) : Importer(urls_) {
+}
+
+bool EBookImporter::canImport(int type) const {
+ return type == Data::Collection::Book;
+}
+
+Tellico::Data::CollPtr EBookImporter::collection() {
+ Data::CollPtr coll(new Data::BookCollection(true));
+#ifdef HAVE_KFILEMETADATA
+ KFileMetaData::ExtractorCollection extractors;
+ foreach(const QUrl& url, urls()) {
+ KFileItem item(url);
+ myDebug() << "Reading" << url.url() << item.mimetype();
+ KFileMetaData::SimpleExtractionResult result(url.toLocalFile(),
+ item.mimetype(),
+ KFileMetaData::ExtractionResult::ExtractMetaData);
+ auto exList = extractors.fetchExtractors(item.mimetype());
+ if(exList.isEmpty()) continue;
+ foreach(auto ex, exList) {
+ ex->extract(&result);
+ }
+ bool isEmpty = true;
+ Data::EntryPtr entry(new Data::Entry(coll));
+ entry->setField(QStringLiteral("comments"), url.toLocalFile());
+ QStringList authors, publishers, genres;
+ KFileMetaData::PropertyMap properties = result.properties();
+ KFileMetaData::PropertyMap::const_iterator it = properties.constBegin();
+ for( ; it != properties.constEnd(); ++it) {
+ const QString value = it.value().toString();
+ if(value.isEmpty()) continue;
+ switch(it.key()) {
+ case KFileMetaData::Property::Title:
+ isEmpty = false; // require a title or author
+ entry->setField(QStringLiteral("title"), value);
+ break;
+
+ case KFileMetaData::Property::Author:
+ isEmpty = false; // require a title or author
+ authors += value;
+ break;
+
+ case KFileMetaData::Property::Publisher:
+ publishers += value;
+ break;
+
+ case KFileMetaData::Property::Subject:
+ case KFileMetaData::Property::Genre:
+ genres += value;
+ break;
+
+ case KFileMetaData::Property::ReleaseYear:
+ entry->setField(QStringLiteral("pub_year"), value);
+ break;
+
+ // is description usually the plot or just comments?
+ case KFileMetaData::Property::Description:
+ entry->setField(QStringLiteral("plot"), value);
+ break;
+
+ default:
+ if(!value.isEmpty()) {
+ myDebug() << "skipping" << it.key() << it.value();
+ }
+ break;
+ }
+ }
+ if(!authors.isEmpty()) {
+ entry->setField(QStringLiteral("author"), authors.join(FieldFormat::delimiterString()));
+ }
+ if(!publishers.isEmpty()) {
+ entry->setField(QStringLiteral("publisher"), publishers.join(FieldFormat::delimiterString()));
+ }
+ if(!genres.isEmpty()) {
+ entry->setField(QStringLiteral("genre"), genres.join(FieldFormat::delimiterString()));
+ }
+ if(!isEmpty) {
+ coll->addEntries(entry);
+ }
+ }
+#endif
+ return coll;
+}
+
+void EBookImporter::slotCancel() {
+ myDebug() << "EBookImporter::slotCancel() - unimplemented";
+}
diff --git a/src/translators/translators.h b/src/translators/ebookimporter.h
similarity index 63%
copy from src/translators/translators.h
copy to src/translators/ebookimporter.h
index 45c384d3..9df575f9 100644
--- a/src/translators/translators.h
+++ b/src/translators/ebookimporter.h
@@ -1,5 +1,5 @@
/***************************************************************************
- Copyright (C) 2003-2009 Robby Stephenson <robby at periapsis.org>
+ Copyright (C) 2023 Robby Stephenson <robby at periapsis.org>
***************************************************************************/
/***************************************************************************
@@ -22,75 +22,41 @@
* *
***************************************************************************/
-#ifndef TRANSLATORS_H
-#define TRANSLATORS_H
+#ifndef TELLICO_IMPORT_EBOOKIMPORTER_H
+#define TELLICO_IMPORT_EBOOKIMPORTER_H
+
+#include "importer.h"
+#include "../datavectors.h"
namespace Tellico {
namespace Import {
- enum Format {
- TellicoXML = 0,
- Bibtex,
- Bibtexml,
- CSV,
- XSLT,
- AudioFile,
- MODS,
- Alexandria,
- FreeDB,
- RIS,
- GCstar,
- FileListing,
- GRS1,
- AMC,
- Griffith,
- PDF,
- Referencer,
- Delicious,
- Goodreads,
- CIW,
- VinoXML,
- BoardGameGeek,
- LibraryThing,
- Collectorz,
- DataCrow,
- MARC
- };
-
- enum Action {
- Replace,
- Append,
- Merge
- };
-
- enum Target {
- None,
- File,
- Dir
- };
- }
-
- namespace Export {
- enum Format {
- TellicoXML = 0,
- TellicoZip,
- Bibtex,
- Bibtexml,
- HTML,
- CSV,
- XSLT,
- Text,
- PilotDB, // Deprecated
- Alexandria,
- ONIX,
- GCstar
- };
-
- enum Target {
- None,
- File,
- Dir
- };
- }
-}
+/**
+ * @author Robby Stephenson
+*/
+class EBookImporter : public Importer {
+Q_OBJECT
+
+public:
+ /**
+ */
+ EBookImporter(const QUrl& url);
+ EBookImporter(const QList<QUrl>& urls);
+
+ /**
+ */
+ virtual Data::CollPtr collection() Q_DECL_OVERRIDE;
+ /**
+ */
+ virtual QWidget* widget(QWidget*) Q_DECL_OVERRIDE { return nullptr; }
+ virtual bool canImport(int type) const Q_DECL_OVERRIDE;
+
+public Q_SLOTS:
+ void slotCancel() Q_DECL_OVERRIDE;
+
+private:
+};
+
+ } // end namespace
+} // end namespace
#endif
diff --git a/src/translators/translators.h b/src/translators/translators.h
index 45c384d3..074bf6bd 100644
--- a/src/translators/translators.h
+++ b/src/translators/translators.h
@@ -53,7 +53,8 @@ namespace Tellico {
LibraryThing,
Collectorz,
DataCrow,
- MARC
+ MARC,
+ EBook
};
enum Action {
More information about the kde-doc-english
mailing list