From 777e9d80241a45fdea156ad8ea535b9406db4507 Mon Sep 17 00:00:00 2001 From: Ivailo Monev Date: Tue, 13 Dec 2022 06:45:19 +0200 Subject: [PATCH] kio: new djvulibre metadata extractor Signed-off-by: Ivailo Monev --- CMakeLists.txt | 8 + kio/metadata/CMakeLists.txt | 22 +++ kio/metadata/kfilemetadata_djvulibre.cpp | 146 +++++++++++++++++++ kio/metadata/kfilemetadata_djvulibre.desktop | 10 ++ kio/metadata/kfilemetadata_djvulibre.h | 34 +++++ 5 files changed, 220 insertions(+) create mode 100644 kio/metadata/kfilemetadata_djvulibre.cpp create mode 100644 kio/metadata/kfilemetadata_djvulibre.desktop create mode 100644 kio/metadata/kfilemetadata_djvulibre.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ffe4834..3ac35fe7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -274,6 +274,14 @@ set_package_properties(Freetype PROPERTIES PURPOSE "Fonts metadata extraction" ) +kde4_optional_find_package(DjVuLibre) +set_package_properties(DjVuLibre PROPERTIES + DESCRIPTION "Open source DjVu library" + URL "https://djvu.sourceforge.net/" + TYPE RECOMMENDED + PURPOSE "DjVu metadata extraction" +) + kde4_optional_find_package(OpenSSL) set_package_properties(OpenSSL PROPERTIES DESCRIPTION "Robust, commercial-grade, full-featured toolkit for general-purpose cryptography and secure communication" diff --git a/kio/metadata/CMakeLists.txt b/kio/metadata/CMakeLists.txt index a5298f04..5e9af421 100644 --- a/kio/metadata/CMakeLists.txt +++ b/kio/metadata/CMakeLists.txt @@ -147,3 +147,25 @@ if (FREETYPE_FOUND) DESTINATION ${KDE4_SERVICES_INSTALL_DIR} ) endif() + +if (DJVULIBRE_FOUND) + include_directories(${DJVULIBRE_INCLUDE_DIR}) + + set(kfilemetadata_djvulibre_SRCS kfilemetadata_djvulibre.cpp) + + kde4_add_plugin(kfilemetadata_djvulibre ${kfilemetadata_djvulibre_SRCS}) + target_link_libraries(kfilemetadata_djvulibre + ${KDE4_KIO_LIBS} + ${DJVULIBRE_LIBRARY} + ) + + install( + TARGETS kfilemetadata_djvulibre + DESTINATION ${KDE4_PLUGIN_INSTALL_DIR} + ) + + install( + FILES kfilemetadata_djvulibre.desktop + DESTINATION ${KDE4_SERVICES_INSTALL_DIR} + ) +endif() diff --git a/kio/metadata/kfilemetadata_djvulibre.cpp b/kio/metadata/kfilemetadata_djvulibre.cpp new file mode 100644 index 00000000..2227f906 --- /dev/null +++ b/kio/metadata/kfilemetadata_djvulibre.cpp @@ -0,0 +1,146 @@ +/* This file is part of the KDE libraries + Copyright (C) 2022 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kfilemetadata_djvulibre.h" +#include "kpluginfactory.h" +#include "kdebug.h" + +#include +#include + +#include +#include + +static const int s_eventstime = 250; +static const int s_sleeptime = 100; + +KFileMetaDataDjVuLibrePlugin::KFileMetaDataDjVuLibrePlugin(QObject* parent, const QVariantList &args) + : KFileMetaDataPlugin(parent) +{ + Q_UNUSED(args); +} + +KFileMetaDataDjVuLibrePlugin::~KFileMetaDataDjVuLibrePlugin() +{ +} + +QList KFileMetaDataDjVuLibrePlugin::metaData(const KUrl &url, const KFileMetaInfo::WhatFlags flags) +{ + Q_UNUSED(flags); + QList result; + const QByteArray urlpath = url.toLocalFile().toUtf8(); + ddjvu_context_t* djvuctx = ddjvu_context_create("kfilemetadata_djvulibre"); + if (!djvuctx) { + kWarning() << "Could not create DjVu context"; + return result; + } + ddjvu_document_t* djvudoc = ddjvu_document_create_by_filename_utf8(djvuctx, urlpath.constData(), FALSE); + if (!djvudoc) { + kWarning() << "Could not create DjVu document"; + ddjvu_context_release(djvuctx); + return result; + } + kDebug() << "Waiting for document decoding to complete"; + while (!ddjvu_document_decoding_done(djvudoc)) { + QCoreApplication::processEvents(QEventLoop::AllEvents, s_eventstime); + QThread::msleep(s_sleeptime); + } + kDebug() << "Done waiting for document decoding to complete"; + const int djvulibrepages = ddjvu_document_get_pagenum(djvudoc); + if (djvulibrepages > 0) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#pageCount"), + QString::number(djvulibrepages) + ) + ); + } + kDebug() << "Waiting for document annotation decoding to complete"; + miniexp_t djvulibreannotation = ddjvu_document_get_anno(djvudoc, 1); + while (djvulibreannotation == miniexp_dummy) { + QCoreApplication::processEvents(QEventLoop::AllEvents, s_eventstime); + QThread::msleep(s_sleeptime); + } + kDebug() << "Waiting for document annotation decoding to complete"; + miniexp_t* djvulibremetadatakeys = ddjvu_anno_get_metadata_keys(djvulibreannotation); + if (djvulibremetadatakeys) { + int counter = 0; + while (djvulibremetadatakeys[counter]) { + // for reference: + // https://linux.die.net/man/1/djvused + const char* djvulibrekeyname = miniexp_to_name(djvulibremetadatakeys[counter]); + const char* djvulibremetadata = ddjvu_anno_get_metadata(djvulibreannotation, djvulibremetadatakeys[counter]); + // qDebug() << Q_FUNC_INFO << djvulibrekeyname << djvulibremetadata; + if (qstricmp(djvulibrekeyname, "title") == 0) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#title"), + QString::fromUtf8(djvulibremetadata) + ) + ); + } else if (qstricmp(djvulibrekeyname, "author") == 0) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#textWriter"), + QString::fromUtf8(djvulibremetadata) + ) + ); + } else if (qstricmp(djvulibrekeyname, "creator") == 0) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/03/22/nco#creator"), + QString::fromUtf8(djvulibremetadata) + ) + ); + } else if (qstricmp(djvulibrekeyname, "subject") == 0) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#subject"), + QString::fromUtf8(djvulibremetadata) + ) + ); + } else if (qstricmp(djvulibrekeyname, "creationdate") == 0) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentCreated"), + QString::fromUtf8(djvulibremetadata) + ) + ); + } else if (qstricmp(djvulibrekeyname, "moddate") == 0) { + result.append( + KFileMetaInfoItem( + QString::fromLatin1("http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentLastModified"), + QString::fromUtf8(djvulibremetadata) + ) + ); + } else { + kDebug() << "Unknown DjVu metadata key" << djvulibrekeyname; + } + counter++; + } + } + ::free(djvulibremetadatakeys); + ddjvu_document_release(djvudoc); + ddjvu_context_release(djvuctx); + return result; +} + +K_PLUGIN_FACTORY(KFileMetaDataDjVuLibrePluginFactory, registerPlugin();) +K_EXPORT_PLUGIN(KFileMetaDataDjVuLibrePluginFactory("kfilemetadata_djvulibre")) + +#include "moc_kfilemetadata_djvulibre.cpp" diff --git a/kio/metadata/kfilemetadata_djvulibre.desktop b/kio/metadata/kfilemetadata_djvulibre.desktop new file mode 100644 index 00000000..23ecb3eb --- /dev/null +++ b/kio/metadata/kfilemetadata_djvulibre.desktop @@ -0,0 +1,10 @@ +[Desktop Entry] +Type=Service +Name=KFileMetaDataDjVuLibrePlugin +GenericName=DjVuLibre +Comment=Extracts metadata from DjVu documents +MimeType=image/vnd.djvu;image/vnd.djvu+multipage;image/x.djvu +X-KDE-Library=kfilemetadata_djvulibre +X-KDE-ServiceTypes=KFileMetaData/Plugin +X-KDE-MetadataKeys=http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#pageCount,http://www.semanticdesktop.org/ontologies/2007/01/19/nie#title,http://www.semanticdesktop.org/ontologies/2007/05/10/nid3#textWriter,http://www.semanticdesktop.org/ontologies/2007/03/22/nco#creator,http://www.semanticdesktop.org/ontologies/2007/01/19/nie#subject,http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentCreated,http://www.semanticdesktop.org/ontologies/2007/01/19/nie#contentLastModified +InitialPreference=1 diff --git a/kio/metadata/kfilemetadata_djvulibre.h b/kio/metadata/kfilemetadata_djvulibre.h new file mode 100644 index 00000000..ad7bb99c --- /dev/null +++ b/kio/metadata/kfilemetadata_djvulibre.h @@ -0,0 +1,34 @@ +/* This file is part of the KDE libraries + Copyright (C) 2022 Ivailo Monev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2, as published by the Free Software Foundation. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KFILEMETADATA_DJVULIBRE_H +#define KFILEMETADATA_DJVULIBRE_H + +#include "kfilemetadata.h" + +class KFileMetaDataDjVuLibrePlugin : public KFileMetaDataPlugin +{ + Q_OBJECT +public: + KFileMetaDataDjVuLibrePlugin(QObject* parent, const QVariantList &args); + ~KFileMetaDataDjVuLibrePlugin(); + + QList metaData(const KUrl &url, const KFileMetaInfo::WhatFlags flags) final; +}; + +#endif // KFILEMETADATA_DJVULIBRE_H