KFileMetaData

extractorcollection.cpp
1 /*
2  SPDX-FileCopyrightText: 2012 Vishesh Handa <[email protected]>
3  SPDX-FileCopyrightText: 2016 Varun Joshi <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7 
8 #include "extractorcollection.h"
9 #include "extractor_p.h"
10 #include "extractorplugin.h"
11 #include "externalextractor.h"
12 #include "kfilemetadata_debug.h"
13 #include "config-kfilemetadata.h"
14 
15 #include <KPluginMetaData>
16 #include <QCoreApplication>
17 #include <QDir>
18 #include <QMimeDatabase>
19 #include <vector>
20 
21 using namespace KFileMetaData;
22 
23 class KFileMetaData::ExtractorCollectionPrivate
24 {
25 public:
26  QMultiHash<QString, Extractor*> m_mimeExtractors;
27 
28  std::vector<Extractor> m_allExtractors;
29 
30  void findExtractors();
31  QList<Extractor*> getExtractors(const QString& mimetype);
32 };
33 
34 ExtractorCollection::ExtractorCollection()
35  : d(new ExtractorCollectionPrivate)
36 {
37  d->findExtractors();
38 }
39 
40 ExtractorCollection::~ExtractorCollection() = default;
41 
42 
43 QList<Extractor*> ExtractorCollection::allExtractors()
44 {
45  QList<Extractor*> plugins;
46  for (auto& ex : d->m_allExtractors) {
47  if (ex.d->initPlugin()) {
48  plugins.push_back(&ex);
49  }
50  }
51  return plugins;
52 }
53 
54 void ExtractorCollectionPrivate::findExtractors()
55 {
56  const QVector<KPluginMetaData> kfilemetadataPlugins =
57  KPluginMetaData::findPlugins(QStringLiteral("kf" QT_STRINGIFY(QT_VERSION_MAJOR) "/kfilemetadata"), {}, KPluginMetaData::AllowEmptyMetaData);
58  for (const KPluginMetaData &plugin : kfilemetadataPlugins) {
59  Extractor extractor;
60  extractor.d->m_pluginPath = plugin.fileName();
61  extractor.setAutoDeletePlugin(Extractor::DoNotDeletePlugin);
62 
63  if (!plugin.rawData().isEmpty()) {
64  qCDebug(KFILEMETADATA_LOG) << "Found plugin with metadata:" << extractor.d->m_pluginPath;
65  extractor.setMetaData(plugin.rawData().toVariantMap());
66  m_allExtractors.push_back(std::move(extractor));
67  } else {
68  qCDebug(KFILEMETADATA_LOG) << "Found plugin without metadata:" << extractor.d->m_pluginPath;
69  if (extractor.d->initPlugin() && !extractor.mimetypes().isEmpty()) {
70  m_allExtractors.push_back(std::move(extractor));
71  }
72  }
73  }
74 
75  const QVector<KPluginMetaData> externalExtractors =
76  KPluginMetaData::findPlugins(QStringLiteral(LIBEXEC_INSTALL_DIR "/kfilemetadata/externalextractors"), {}, KPluginMetaData::AllowEmptyMetaData);
77  for (const KPluginMetaData &externalPlugin : externalExtractors) {
78  qCDebug(KFILEMETADATA_LOG) << "Adding plugin - " << externalPlugin.fileName();
79 
80  Extractor extractor;
81  ExternalExtractor *plugin = new ExternalExtractor(externalPlugin.fileName());
82  if (plugin && !plugin->mimetypes().isEmpty()) {
83  extractor.setExtractorPlugin(plugin);
84  extractor.setAutoDeletePlugin(Extractor::AutoDeletePlugin);
85  m_allExtractors.push_back(std::move(extractor));
86  }
87  }
88 
89  for (Extractor& extractor : m_allExtractors) {
90  auto pluginProperties = extractor.extractorProperties();
91  if (!pluginProperties.isEmpty()) {
92  auto mimetypeProperties = pluginProperties[QLatin1String("MimeTypes")];
93  const auto mimetypes = mimetypeProperties.toMap().keys();
94  for (const QString &mimetype : mimetypes) {
95  m_mimeExtractors.insert(mimetype, &extractor);
96  }
97  } else if (extractor.d->m_plugin) {
98  const auto mimetypes = extractor.mimetypes();
99  for (const QString &mimetype : mimetypes) {
100  m_mimeExtractors.insert(mimetype, &extractor);
101  }
102  }
103  }
104 }
105 
106 QList<Extractor*> ExtractorCollectionPrivate::getExtractors(const QString& mimetype)
107 {
108  QList<Extractor*> extractors = m_mimeExtractors.values(mimetype);
109 
110  if (extractors.isEmpty()) {
111  qCDebug(KFILEMETADATA_LOG) << "No extractor for" << mimetype;
112  return extractors;
113  }
114 
115  qCDebug(KFILEMETADATA_LOG) << "Fetching extractors for" << mimetype;
116  Extractor* failed = nullptr;
117  for (auto ex : extractors) {
118  if (!ex->d->initPlugin()) {
119  failed = ex;
120  break;
121  }
122  }
123 
124  if (!failed) {
125  return extractors;
126  }
127 
128  auto it = m_mimeExtractors.begin();
129  while (it != m_mimeExtractors.end()) {
130  if (it.value() == failed) {
131  it = m_mimeExtractors.erase(it);
132  } else {
133  ++it;
134  }
135  }
136  return getExtractors(mimetype);
137 }
138 
140 {
141  QList<Extractor*> plugins = d->getExtractors(mimetype);
142  if (!plugins.isEmpty()) {
143  return plugins;
144  }
145 
146  // try to find the best matching more generic extractor by mimetype inheritance
147  QMimeDatabase db;
148  auto type = db.mimeTypeForName(mimetype);
149  const QStringList ancestors = type.allAncestors();
150 
151  for (const auto &ancestor : ancestors) {
152  if (ancestor == QLatin1String("application/octet-stream")) {
153  continue;
154  }
155  QList<Extractor*> plugins = d->getExtractors(ancestor);
156  if (!plugins.isEmpty()) {
157  qCDebug(KFILEMETADATA_LOG) << "Using inherited mimetype" << ancestor << "for" << mimetype;
158  return plugins;
159  }
160  }
161 
162  return plugins;
163 }
void push_back(const T &value)
KIOCORE_EXPORT MimetypeJob * mimetype(const QUrl &url, JobFlags flags=DefaultFlags)
QMimeType mimeTypeForName(const QString &nameOrAlias) const const
bool isEmpty() const const
static QVector< KPluginMetaData > findPlugins(const QString &directory, std::function< bool(const KPluginMetaData &)> filter, KPluginMetaDataOption option)
QList< Extractor * > fetchExtractors(const QString &mimetype) const
Fetch the extractors which can be used to extract data for the respective file with the given mimetyp...
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu May 26 2022 03:46:07 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.