diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -166,6 +166,15 @@ LINK_LIBRARIES Qt5::Test KF5::FileMetaData ) +set(writercollection_SRCS + writercollectiontest.cpp +) + +ecm_add_test(${writercollection_SRCS} + TEST_NAME "writercollectiontest" + LINK_LIBRARIES Qt5::Test KF5::FileMetaData +) + # # XML # diff --git a/src/writer.h b/src/writer.h --- a/src/writer.h +++ b/src/writer.h @@ -39,6 +39,13 @@ class KFILEMETADATA_EXPORT Writer { public: + class WriterPrivate; + + enum WriterPluginOwnership { + AutoDeletePlugin, + DoNotDeletePlugin, + }; + virtual ~Writer(); void write(const WriteData& data); @@ -50,10 +57,9 @@ void operator =(const Writer&); - class WriterPrivate; - WriterPrivate *d_ptr; - Q_DECLARE_PRIVATE(Writer) + void setAutoDeletePlugin(WriterPluginOwnership autoDelete); + WriterPrivate *d; friend class WriterCollection; }; } diff --git a/src/writer.cpp b/src/writer.cpp --- a/src/writer.cpp +++ b/src/writer.cpp @@ -28,25 +28,26 @@ using namespace KFileMetaData; Writer::Writer() - : d_ptr(new WriterPrivate) + : d(new WriterPrivate) { } Writer::~Writer() { - Q_D(Writer); - delete d->m_plugin; - delete d_ptr; + delete d; } void Writer::write(const WriteData& data) { - Q_D(Writer); d->m_plugin->write(data); } QStringList Writer::mimetypes() const { - Q_D(const Writer); return d->m_plugin->writeMimetypes(); } + +void Writer::setAutoDeletePlugin(WriterPluginOwnership autoDelete) +{ + d->m_autoDeletePlugin = autoDelete; +} diff --git a/src/writer_p.h b/src/writer_p.h --- a/src/writer_p.h +++ b/src/writer_p.h @@ -31,7 +31,15 @@ class Q_DECL_HIDDEN Writer::WriterPrivate { public: + ~WriterPrivate() { + if (m_autoDeletePlugin == AutoDeletePlugin) { + delete m_plugin; + } + } + WriterPlugin *m_plugin = nullptr; + + WriterPluginOwnership m_autoDeletePlugin = AutoDeletePlugin; }; } diff --git a/src/writercollection.h b/src/writercollection.h --- a/src/writercollection.h +++ b/src/writercollection.h @@ -45,8 +45,7 @@ private: class WriterCollectionPrivate; - WriterCollectionPrivate* d_ptr; - Q_DECLARE_PRIVATE(WriterCollection) + WriterCollectionPrivate* d; }; } diff --git a/src/writercollection.cpp b/src/writercollection.cpp --- a/src/writercollection.cpp +++ b/src/writercollection.cpp @@ -32,24 +32,25 @@ #include #include #include +#include using namespace KFileMetaData; class Q_DECL_HIDDEN WriterCollection::WriterCollectionPrivate { public: QHash m_writers; - QList allWriters() const; + QList m_allWriters; + + void findWriters(); }; WriterCollection::WriterCollection() - : d_ptr(new WriterCollectionPrivate) + : d(new WriterCollectionPrivate) { - Q_D(WriterCollection); - const QList all = d->allWriters(); - - for (Writer* writer : all) { + d->findWriters(); + for (Writer* writer : qAsConst(d->m_allWriters)) { const QStringList lst = writer->mimetypes(); for (const QString& type : lst) { d->m_writers.insertMulti(type, writer); @@ -59,13 +60,11 @@ WriterCollection::~WriterCollection() { - Q_D(WriterCollection); - qDeleteAll(d->m_writers.begin(), d->m_writers.end()); + qDeleteAll(d->m_allWriters); delete d; } - -QList WriterCollection::WriterCollectionPrivate::allWriters() const +void WriterCollection::WriterCollectionPrivate::findWriters() { QStringList plugins; QStringList pluginPaths; @@ -106,7 +105,6 @@ } externalPlugins.clear(); - QList writers; for (const QString& pluginPath : qAsConst(pluginPaths)) { QPluginLoader loader(pluginPath); @@ -121,9 +119,10 @@ WriterPlugin* plugin = qobject_cast(obj); if (plugin) { Writer* writer = new Writer; - writer->d_ptr->m_plugin = plugin; + writer->d->m_plugin = plugin; + writer->setAutoDeletePlugin(Writer::DoNotDeletePlugin); - writers << writer; + m_allWriters << writer; } else { qCDebug(KFILEMETADATA_LOG) << "Plugin could not be converted to a WriterPlugin"; qCDebug(KFILEMETADATA_LOG) << pluginPath; @@ -137,23 +136,33 @@ for (const QString& externalPluginPath : qAsConst(externalPluginPaths)) { ExternalWriter *plugin = new ExternalWriter(externalPluginPath); Writer* writer = new Writer; - writer->d_ptr->m_plugin = plugin; + writer->d->m_plugin = plugin; + writer->setAutoDeletePlugin(Writer::AutoDeletePlugin); - writers << writer; + m_allWriters << writer; } - - return writers; } QList WriterCollection::fetchWriters(const QString& mimetype) const { - Q_D(const WriterCollection); QList plugins = d->m_writers.values(mimetype); - if (plugins.isEmpty()) { - auto it = d->m_writers.constBegin(); - for (; it != d->m_writers.constEnd(); ++it) { - if (mimetype.startsWith(it.key())) - plugins << it.value(); + if (!plugins.isEmpty()) { + return plugins; + } + + // try to find the best matching more generic extractor by mimetype inheritance + QMimeDatabase db; + auto type = db.mimeTypeForName(mimetype); + const QStringList ancestors = type.allAncestors(); + + for (auto ancestor : ancestors) { + if (ancestor == QLatin1String("application/octet-stream")) { + continue; + } + QList plugins = d->m_writers.values(ancestor); + if (!plugins.isEmpty()) { + qCDebug(KFILEMETADATA_LOG) << "Using inherited mimetype" << ancestor << "for" << mimetype; + return plugins; } } diff --git a/src/writers/CMakeLists.txt b/src/writers/CMakeLists.txt --- a/src/writers/CMakeLists.txt +++ b/src/writers/CMakeLists.txt @@ -7,6 +7,7 @@ ${TAGLIB_LIBRARIES} ) + set_target_properties(kfilemetadata_taglibwriter PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/kf5/kfilemetadata/writers") install( TARGETS kfilemetadata_taglibwriter DESTINATION ${PLUGIN_INSTALL_DIR}/kf5/kfilemetadata/writers)