KDECore
kpluginfactory.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 2007 Matthias Kretz <kretz@kde.org> 00003 Copyright (C) 2007 Bernhard Loos <nhuh.put@web.de> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 00020 */ 00021 00022 #include "kpluginfactory.h" 00023 #include "kpluginfactory_p.h" 00024 #include <kdebug.h> 00025 #include <kglobal.h> 00026 00027 #include <QtCore/QObjectCleanupHandler> 00028 00029 K_GLOBAL_STATIC(QObjectCleanupHandler, factorycleanup) 00030 00031 extern int kLibraryDebugArea(); 00032 00033 KPluginFactory::KPluginFactory(const char *componentName, const char *catalogName, QObject *parent) 00034 : QObject(parent), d_ptr(new KPluginFactoryPrivate) 00035 { 00036 Q_D(KPluginFactory); 00037 d->q_ptr = this; 00038 00039 if (componentName) 00040 d->componentData = KComponentData(componentName, catalogName); 00041 00042 factorycleanup->add(this); 00043 } 00044 00045 #ifndef KDE_NO_DEPRECATED 00046 KPluginFactory::KPluginFactory(const KAboutData *aboutData, QObject *parent) 00047 : QObject(parent), d_ptr(new KPluginFactoryPrivate) 00048 { 00049 Q_D(KPluginFactory); 00050 d->q_ptr = this; 00051 d->componentData = KComponentData(*aboutData); 00052 00053 factorycleanup->add(this); 00054 } 00055 #endif 00056 00057 KPluginFactory::KPluginFactory(const KAboutData &aboutData, QObject *parent) 00058 : QObject(parent), d_ptr(new KPluginFactoryPrivate) 00059 { 00060 Q_D(KPluginFactory); 00061 d->q_ptr = this; 00062 d->componentData = KComponentData(aboutData); 00063 00064 factorycleanup->add(this); 00065 } 00066 00067 #ifndef KDE_NO_DEPRECATED 00068 KPluginFactory::KPluginFactory(QObject *parent) 00069 : QObject(parent), d_ptr(new KPluginFactoryPrivate()) 00070 { 00071 Q_D(KPluginFactory); 00072 d->q_ptr = this; 00073 factorycleanup->add(this); 00074 } 00075 #endif 00076 00077 KPluginFactory::KPluginFactory(KPluginFactoryPrivate &d, QObject *parent) 00078 : QObject(parent), d_ptr(&d) 00079 { 00080 factorycleanup->add(this); 00081 } 00082 00083 KPluginFactory::~KPluginFactory() 00084 { 00085 Q_D(KPluginFactory); 00086 00087 if (d->catalogInitialized && d->componentData.isValid()) { 00088 KGlobal::locale()->removeCatalog(d->componentData.catalogName()); 00089 } 00090 00091 delete d_ptr; 00092 } 00093 00094 KComponentData KPluginFactory::componentData() const 00095 { 00096 Q_D(const KPluginFactory); 00097 return d->componentData; 00098 } 00099 00100 void KPluginFactory::registerPlugin(const QString &keyword, const QMetaObject *metaObject, CreateInstanceFunction instanceFunction) 00101 { 00102 Q_D(KPluginFactory); 00103 00104 Q_ASSERT(metaObject); 00105 00106 // we allow different interfaces to be registered without keyword 00107 if (!keyword.isEmpty()) { 00108 if (d->createInstanceHash.contains(keyword)) { 00109 kFatal(kLibraryDebugArea()) << "A plugin with the keyword" << keyword << "was already registered. A keyword must be unique!"; 00110 } 00111 d->createInstanceHash.insert(keyword, KPluginFactoryPrivate::Plugin(metaObject, instanceFunction)); 00112 } else { 00113 QList<KPluginFactoryPrivate::Plugin> clashes(d->createInstanceHash.values(keyword)); 00114 const QMetaObject *superClass = metaObject->superClass(); 00115 if (superClass) { 00116 foreach (const KPluginFactoryPrivate::Plugin &plugin, clashes) { 00117 for (const QMetaObject *otherSuper = plugin.first->superClass(); otherSuper; 00118 otherSuper = otherSuper->superClass()) { 00119 if (superClass == otherSuper) { 00120 kFatal(kLibraryDebugArea()) << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins."; 00121 } 00122 } 00123 } 00124 } 00125 foreach (const KPluginFactoryPrivate::Plugin &plugin, clashes) { 00126 superClass = plugin.first->superClass(); 00127 if (superClass) { 00128 for (const QMetaObject *otherSuper = metaObject->superClass(); otherSuper; 00129 otherSuper = otherSuper->superClass()) { 00130 if (superClass == otherSuper) { 00131 kFatal(kLibraryDebugArea()) << "Two plugins with the same interface(" << superClass->className() << ") were registered. Use keywords to identify the plugins."; 00132 } 00133 } 00134 } 00135 } 00136 d->createInstanceHash.insertMulti(keyword, KPluginFactoryPrivate::Plugin(metaObject, instanceFunction)); 00137 } 00138 } 00139 00140 #ifndef KDE_NO_DEPRECATED 00141 QObject *KPluginFactory::createObject(QObject *parent, const char *className, const QStringList &args) 00142 { 00143 Q_UNUSED(parent); 00144 Q_UNUSED(className); 00145 Q_UNUSED(args); 00146 return 0; 00147 } 00148 #endif 00149 00150 #ifndef KDE_NO_DEPRECATED 00151 KParts::Part *KPluginFactory::createPartObject(QWidget *parentWidget, QObject *parent, const char *classname, const QStringList &args) 00152 { 00153 Q_UNUSED(parent); 00154 Q_UNUSED(parentWidget); 00155 Q_UNUSED(classname); 00156 Q_UNUSED(args); 00157 return 0; 00158 } 00159 #endif 00160 00161 QObject *KPluginFactory::create(const char *iface, QWidget *parentWidget, QObject *parent, const QVariantList &args, const QString &keyword) 00162 { 00163 Q_D(KPluginFactory); 00164 00165 QObject *obj = 0; 00166 00167 if (!d->catalogInitialized) { 00168 d->catalogInitialized = true; 00169 setupTranslations(); 00170 } 00171 00172 #ifndef KDE_NO_DEPRECATED 00173 if (keyword.isEmpty()) { 00174 00175 // kde3-kparts compatibility, remove in kde5 00176 const char* kpartsIface = iface; 00177 if (args.contains(QVariant(QString::fromLatin1("Browser/View")))) 00178 kpartsIface = "Browser/View"; 00179 00180 const QStringList argsStringList = variantListToStringList(args); 00181 00182 if ((obj = reinterpret_cast<QObject *>(createPartObject(parentWidget, parent, kpartsIface, argsStringList)))) { 00183 objectCreated(obj); 00184 return obj; 00185 } 00186 00187 if ((obj = createObject(parent, iface, argsStringList))) { 00188 objectCreated(obj); 00189 return obj; 00190 } 00191 } 00192 #endif 00193 00194 const QList<KPluginFactoryPrivate::Plugin> candidates(d->createInstanceHash.values(keyword)); 00195 // for !keyword.isEmpty() candidates.count() is 0 or 1 00196 00197 foreach (const KPluginFactoryPrivate::Plugin &plugin, candidates) { 00198 for (const QMetaObject *current = plugin.first; current; current = current->superClass()) { 00199 if (0 == qstrcmp(iface, current->className())) { 00200 if (obj) { 00201 kFatal(kLibraryDebugArea()) << "ambiguous interface requested from a DSO containing more than one plugin"; 00202 } 00203 obj = plugin.second(parentWidget, parent, args); 00204 break; 00205 } 00206 } 00207 } 00208 00209 if (obj) { 00210 emit objectCreated(obj); 00211 } 00212 return obj; 00213 } 00214 00215 void KPluginFactory::setupTranslations() 00216 { 00217 Q_D(KPluginFactory); 00218 00219 if (!d->componentData.isValid()) 00220 return; 00221 00222 KGlobal::locale()->insertCatalog(d->componentData.catalogName()); 00223 } 00224 00225 void KPluginFactory::setComponentData(const KComponentData &kcd) 00226 { 00227 Q_D(KPluginFactory); 00228 d->componentData = kcd; 00229 } 00230 00231 // KDE5 TODO: should be static, and possibly public (for apps to use) 00232 QStringList KPluginFactory::variantListToStringList(const QVariantList &list) 00233 { 00234 QStringList stringlist; 00235 Q_FOREACH(const QVariant& var, list) 00236 stringlist << var.toString(); 00237 return stringlist; 00238 } 00239 00240 // KDE5 TODO: should be static, and possibly public (for apps to use) 00241 QVariantList KPluginFactory::stringListToVariantList(const QStringList &list) 00242 { 00243 QVariantList variantlist; 00244 Q_FOREACH(const QString& str, list) 00245 variantlist << QVariant(str); 00246 return variantlist; 00247 } 00248 00249 #include "kpluginfactory.moc"
KDE 4.6 API Reference