21#include "typepluginloader_p.h"
24#include "itemserializer_p.h"
25#include "itemserializerplugin.h"
33#include <QtCore/QHash>
34#include <QtCore/QString>
35#include <QtCore/QByteArray>
36#include <QtCore/QStringList>
38#include <boost/graph/adjacency_list.hpp>
39#include <boost/graph/topological_sort.hpp>
42#include "pluginloader_p.h"
47static const char LEGACY_NAME[] =
"legacy";
48static const char DEFAULT_NAME[] =
"default";
49static const char _APPLICATION_OCTETSTREAM[] =
"application/octet-stream";
53K_GLOBAL_STATIC(DefaultItemSerializerPlugin, s_defaultItemSerializerPlugin)
63 explicit PluginEntry(
const QString &identifier, QObject *plugin = 0)
64 : mIdentifier(identifier)
69 QObject *plugin()
const
75 QObject *
object = PluginLoader::self()->createForName(mIdentifier);
77 kWarning() <<
"ItemSerializerPluginLoader: "
78 <<
"plugin" << mIdentifier <<
"is not valid!" << endl;
81 mPlugin = s_defaultItemSerializerPlugin;
85 if (!qobject_cast<ItemSerializerPlugin *>(mPlugin)) {
86 kWarning() <<
"ItemSerializerPluginLoader: "
87 <<
"plugin" << mIdentifier <<
"doesn't provide interface ItemSerializerPlugin!" << endl;
90 mPlugin = s_defaultItemSerializerPlugin;
98 const char *pluginClassName()
const
100 return plugin()->metaObject()->className();
103 QString identifier()
const
108 bool operator<(
const PluginEntry &other)
const
110 return mIdentifier < other.mIdentifier;
113 bool operator<(
const QString &identifier)
const
115 return mIdentifier < identifier;
120 mutable QObject *mPlugin;
123static bool operator<(
const QString &identifier,
const PluginEntry &entry)
125 return identifier < entry.identifier();
131 explicit MimeTypeEntry(
const QString &mimeType)
132 : m_mimeType(mimeType)
134 , m_pluginsByMetaTypeId()
143 void add(
const QByteArray &class_,
const PluginEntry &entry)
145 m_pluginsByMetaTypeId.clear();
146 m_plugins.insert(class_, entry);
149 const PluginEntry *plugin(
const QByteArray &class_)
const
151 const QHash<QByteArray, PluginEntry>::const_iterator it = m_plugins.find(class_);
152 return it == m_plugins.end() ? 0 : it.operator->();
155 const PluginEntry *defaultPlugin()
const
158 if (
const PluginEntry *pe = plugin(DEFAULT_NAME)) {
164 bool sawZero =
false;
165 for (QMap<
int, QHash<QByteArray, PluginEntry>::const_iterator>::const_iterator it = m_pluginsByMetaTypeId.constBegin(), end = m_pluginsByMetaTypeId.constEnd(); it != end; ++it) {
168 }
else if (*it != m_plugins.end()) {
169 return it->operator->();
174 for (QHash<QByteArray, PluginEntry>::const_iterator it = m_plugins.constBegin(), end = m_plugins.constEnd(); it != end; ++it) {
175 if (it.key() == LEGACY_NAME) {
178 return it.operator->();
189 const PluginEntry *plugin(
int metaTypeId)
const
191 const QMap<int, QHash<QByteArray, PluginEntry>::const_iterator> &c_pluginsByMetaTypeId = m_pluginsByMetaTypeId;
192 QMap<int, QHash<QByteArray, PluginEntry>::const_iterator>::const_iterator it = c_pluginsByMetaTypeId.find(metaTypeId);
193 if (it == c_pluginsByMetaTypeId.end()) {
194 it = QMap<int, QHash<QByteArray, PluginEntry>::const_iterator>::const_iterator(m_pluginsByMetaTypeId.insert(metaTypeId, m_plugins.find(metaTypeId ? QMetaType::typeName(metaTypeId) : LEGACY_NAME)));
196 return *it == m_plugins.end() ? 0 : it->operator->();
199 const PluginEntry *plugin(
const QVector<int> &metaTypeIds,
int &chosen)
const
201 bool sawZero =
false;
202 for (QVector<int>::const_iterator it = metaTypeIds.begin(), end = metaTypeIds.end(); it != end; ++it) {
205 }
else if (
const PluginEntry *
const entry = plugin(*it)) {
219 QHash<QByteArray, PluginEntry> m_plugins;
220 mutable QMap<int, QHash<QByteArray, PluginEntry>::const_iterator> m_pluginsByMetaTypeId;
223static bool operator<(
const MimeTypeEntry &lhs,
const MimeTypeEntry &rhs)
225 return lhs.type() < rhs.type();
228static bool operator<(
const MimeTypeEntry &lhs,
const QString &rhs)
230 return lhs.type() < rhs;
233static bool operator<(
const QString &lhs,
const MimeTypeEntry &rhs)
235 return lhs < rhs.type();
238static QString format(
const QString &mimeType,
const QVector<int> &metaTypeIds) {
239 if (metaTypeIds.empty()) {
240 return QLatin1String(
"default for ") + mimeType;
242 QStringList classTypes;
243 Q_FOREACH (
int metaTypeId, metaTypeIds) {
244 classTypes.push_back(QString::fromLatin1(metaTypeId ? QMetaType::typeName(metaTypeId) : LEGACY_NAME));
246 return mimeType + QLatin1String(
"@{") + classTypes.join(QLatin1String(
",")) + QLatin1Char(
'}');
253 : mDefaultPlugin(PluginEntry(QLatin1String(
"application/octet-stream@QByteArray"), s_defaultItemSerializerPlugin))
256 const PluginLoader *pl = PluginLoader::self();
258 kWarning() <<
"Cannot instantiate plugin loader!" << endl;
261 const QStringList names = pl->names();
262 kDebug() <<
"ItemSerializerPluginLoader: "
263 <<
"found" << names.size() <<
"plugins." << endl;
264 QMap<QString, MimeTypeEntry> map;
265 QRegExp rx(QLatin1String(
"(.+)@(.+)"));
266 Q_FOREACH (
const QString &name, names) {
267 if (rx.exactMatch(name)) {
268 KMimeType::Ptr mime = KMimeType::mimeType(rx.cap(1), KMimeType::ResolveAliases);
270 const QString mimeType = mime->name();
271 const QByteArray classType = rx.cap(2).toLatin1();
272 QMap<QString, MimeTypeEntry>::iterator it = map.find(mimeType);
273 if (it == map.end()) {
274 it = map.insert(mimeType, MimeTypeEntry(mimeType));
276 it->add(classType, PluginEntry(name));
279 kDebug() <<
"ItemSerializerPluginLoader: "
280 <<
"name" << name <<
"doesn't look like mimetype@classtype" << endl;
283 const QString APPLICATION_OCTETSTREAM = QLatin1String(_APPLICATION_OCTETSTREAM);
284 QMap<QString, MimeTypeEntry>::iterator it = map.find(APPLICATION_OCTETSTREAM);
285 if (it == map.end()) {
286 it = map.insert(APPLICATION_OCTETSTREAM, MimeTypeEntry(APPLICATION_OCTETSTREAM));
288 it->add(
"QByteArray", mDefaultPlugin);
289 it->add(LEGACY_NAME, mDefaultPlugin);
290 const int size = map.size();
291 allMimeTypes.reserve(size);
292 std::copy(map.begin(), map.end(), std::back_inserter(allMimeTypes));
295 QObject *findBestMatch(
const QString &type,
const QVector<int> &metaTypeId, TypePluginLoader::Options opt)
297 if (QObject *
const plugin = findBestMatch(type, metaTypeId)) { {
298 if ((opt &TypePluginLoader::NoDefault) && plugin == mDefaultPlugin.plugin()) {
307 QObject *findBestMatch(
const QString &type,
const QVector<int> &metaTypeIds)
309 if (mOverridePlugin) {
310 return mOverridePlugin;
312 if (QObject *
const plugin = cacheLookup(type, metaTypeIds)) {
317 QObject *
const plugin = findBestMatchImpl(type, metaTypeIds, chosen);
318 if (metaTypeIds.empty()) {
320 cachedDefaultPlugins[type] = plugin;
324 cachedPlugins[type][chosen] = plugin;
329 void overrideDefaultPlugin(QObject *p)
335 QObject *findBestMatchImpl(
const QString &type,
const QVector<int> &metaTypeIds,
int &chosen)
const
337 KMimeType::Ptr mimeType = KMimeType::mimeType(type, KMimeType::ResolveAliases);
338 if (mimeType.isNull()) {
339 return mDefaultPlugin.plugin();
343 QVector<int> matchingIndexes;
344 for (
int i = 0, end = allMimeTypes.size(); i < end; ++i) {
345 if (mimeType->is(allMimeTypes[i].type())) {
346 matchingIndexes.append(i);
352 if (matchingIndexes.size() <= 1) {
355 boost::adjacency_list<> graph(matchingIndexes.size());
356 for (
int i = 0, end = matchingIndexes.size(); i != end; ++i) {
357 KMimeType::Ptr mimeType = KMimeType::mimeType(allMimeTypes[matchingIndexes[i]].type(), KMimeType::ResolveAliases);
358 if (mimeType.isNull()) {
361 for (
int j = 0; j != end; ++j) {
362 if (i != j && mimeType->is(allMimeTypes[matchingIndexes[j]].type())) {
363 boost::add_edge(j, i, graph);
368 order.reserve(matchingIndexes.size());
370 boost::topological_sort(graph, std::back_inserter(order));
371 }
catch (boost::not_a_dag &e) {
372 kWarning() <<
"Mimetype tree is not a DAG!";
373 return mDefaultPlugin.plugin();
379 for (QVector<int>::const_iterator it = order.constBegin(), end = order.constEnd(); it != end; ++it) {
382 const MimeTypeEntry &mt = allMimeTypes[matchingIndexes[*it]];
383 if (metaTypeIds.empty()) {
384 if (
const PluginEntry *
const entry = mt.defaultPlugin()) {
386 return entry->plugin();
390 }
else if (
const PluginEntry *
const entry = mt.plugin(metaTypeIds, chosen)) {
392 return entry->plugin();
400 return mDefaultPlugin.plugin();
403 std::vector<MimeTypeEntry> allMimeTypes;
404 QHash<QString, QMap<int, QObject *> > cachedPlugins;
405 QHash<QString, QObject *> cachedDefaultPlugins;
408 QObject *cacheLookup(
const QString &mimeType,
const QVector<int> &metaTypeIds)
const {
409 if (metaTypeIds.empty()) {
410 const QHash<QString, QObject *>::const_iterator hit = cachedDefaultPlugins.find(mimeType);
411 if (hit != cachedDefaultPlugins.end()) {
416 const QHash<QString, QMap<int, QObject *> >::const_iterator hit = cachedPlugins.find(mimeType);
417 if (hit == cachedPlugins.end()) {
420 bool sawZero =
false;
421 for (QVector<int>::const_iterator it = metaTypeIds.begin(), end = metaTypeIds.end(); it != end; ++it) {
424 }
else if (QObject *
const o = hit->value(*it)) {
429 return hit->value(0);
435 PluginEntry mDefaultPlugin;
436 QObject *mOverridePlugin;
439K_GLOBAL_STATIC(PluginRegistry, s_pluginRegistry)
441QObject *TypePluginLoader::objectForMimeTypeAndClass(const QString &mimetype, const QVector<
int> &metaTypeIds, Options opt)
443 return s_pluginRegistry->findBestMatch(mimetype, metaTypeIds, opt);
447QObject *TypePluginLoader::legacyObjectForMimeType(
const QString &mimetype) {
449 return objectForMimeTypeAndClass(mimetype, QVector<int>(1, 0));
464 ItemSerializerPlugin *plugin = qobject_cast<ItemSerializerPlugin *>(legacyObjectForMimeType(mimetype));
477 s_pluginRegistry->overrideDefaultPlugin(p);
The base class for item type serializer plugins.
void overridePluginLookup(QObject *plugin)
Override the plugin-lookup with plugin.
ItemSerializerPlugin * pluginForMimeTypeAndClass(const QString &mimetype, const QVector< int > &metaTypeIds, Options options=NoOptions)
Returns the item serializer plugin that matches the given mimetype, and any of the classes described ...
QObject * objectForMimeTypeAndClass(const QString &mimetype, const QVector< int > &metaTypeIds, Options options=NoOptions)
Returns the type plugin object that matches the given mimetype, and any of the classes described by m...
ItemSerializerPlugin * defaultPluginForMimeType(const QString &mimetype)
Returns the default item serializer plugin that matches the given mimetype.
QObject * defaultObjectForMimeType(const QString &mimetype)
Returns the default type plugin object that matches the given mimetype.
FreeBusyManager::Singleton.