KParts
plugin.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE project 00002 Copyright (C) 1999 Simon Hausmann <hausmann@kde.org> 00003 (C) 1999 David Faure <faure@kde.org> 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 #include <kparts/plugin.h> 00022 #include <kparts/part.h> 00023 #include <kparts/componentfactory.h> 00024 00025 #include <assert.h> 00026 00027 #include <QtCore/QFile> 00028 #include <QtCore/QObject> 00029 #include <QtCore/QFileInfo> 00030 00031 #include <kcomponentdata.h> 00032 #include <kstandarddirs.h> 00033 #include <kdebug.h> 00034 #include <kxmlguifactory.h> 00035 #include <klocale.h> 00036 #include <kdesktopfile.h> 00037 #include <kconfiggroup.h> 00038 00039 using namespace KParts; 00040 00041 class Plugin::PluginPrivate 00042 { 00043 public: 00044 KComponentData m_parentInstance; 00045 QString m_library; // filename of the library 00046 }; 00047 00048 Plugin::Plugin( QObject* parent ) 00049 : QObject( parent ),d(new PluginPrivate()) 00050 { 00051 //kDebug() << className(); 00052 } 00053 00054 Plugin::~Plugin() 00055 { 00056 delete d; 00057 } 00058 00059 QString Plugin::xmlFile() const 00060 { 00061 QString path = KXMLGUIClient::xmlFile(); 00062 00063 if ( !d->m_parentInstance.isValid() || ( path.length() > 0 && path[ 0 ] == '/' ) ) 00064 return path; 00065 00066 QString absPath = KStandardDirs::locate( "data", d->m_parentInstance.componentName() + '/' + path ); 00067 assert( !absPath.isEmpty() ); 00068 return absPath; 00069 } 00070 00071 QString Plugin::localXMLFile() const 00072 { 00073 QString path = KXMLGUIClient::xmlFile(); 00074 00075 if ( !d->m_parentInstance.isValid() || ( path.length() > 0 && path[ 0 ] == '/' ) ) 00076 return path; 00077 00078 QString absPath = KStandardDirs::locateLocal( "data", d->m_parentInstance.componentName() + '/' + path ); 00079 assert( !absPath.isEmpty() ); 00080 return absPath; 00081 } 00082 00083 //static 00084 QList<Plugin::PluginInfo> Plugin::pluginInfos(const KComponentData &componentData) 00085 { 00086 if (!componentData.isValid()) 00087 kError(1000) << "No componentData ???" << endl; 00088 00089 QList<PluginInfo> plugins; 00090 00091 // TODO KDE5: change * into *.rc and remove test for .desktop from the for loop below. 00092 const QStringList pluginDocs = componentData.dirs()->findAllResources( 00093 "data", componentData.componentName()+"/kpartplugins/*", KStandardDirs::Recursive ); 00094 00095 QMap<QString,QStringList> sortedPlugins; 00096 00097 QStringList::ConstIterator pIt = pluginDocs.begin(); 00098 QStringList::ConstIterator pEnd = pluginDocs.end(); 00099 for (; pIt != pEnd; ++pIt ) 00100 { 00101 QFileInfo fInfo( *pIt ); 00102 if ( fInfo.completeSuffix() == QLatin1String( "desktop" ) ) 00103 continue; 00104 00105 QMap<QString,QStringList>::Iterator mapIt = sortedPlugins.find( fInfo.fileName() ); 00106 if ( mapIt == sortedPlugins.end() ) 00107 mapIt = sortedPlugins.insert( fInfo.fileName(), QStringList() ); 00108 00109 mapIt.value().append( *pIt ); 00110 } 00111 00112 QMap<QString,QStringList>::ConstIterator mapIt = sortedPlugins.constBegin(); 00113 QMap<QString,QStringList>::ConstIterator mapEnd = sortedPlugins.constEnd(); 00114 for (; mapIt != mapEnd; ++mapIt ) 00115 { 00116 PluginInfo info; 00117 QString doc; 00118 info.m_absXMLFileName = KXMLGUIClient::findMostRecentXMLFile( mapIt.value(), doc ); 00119 if ( info.m_absXMLFileName.isEmpty() ) 00120 continue; 00121 00122 kDebug( 1000 ) << "found KParts Plugin : " << info.m_absXMLFileName; 00123 info.m_relXMLFileName = "kpartplugins/"; 00124 info.m_relXMLFileName += mapIt.key(); 00125 00126 info.m_document.setContent( doc ); 00127 if ( info.m_document.documentElement().isNull() ) 00128 continue; 00129 00130 plugins.append( info ); 00131 } 00132 00133 return plugins; 00134 } 00135 00136 void Plugin::loadPlugins(QObject *parent, const KComponentData &componentData) 00137 { 00138 loadPlugins( parent, pluginInfos( componentData ), componentData ); 00139 } 00140 00141 void Plugin::loadPlugins(QObject *parent, const QList<PluginInfo> &pluginInfos, const KComponentData &componentData) 00142 { 00143 QList<PluginInfo>::ConstIterator pIt = pluginInfos.begin(); 00144 QList<PluginInfo>::ConstIterator pEnd = pluginInfos.end(); 00145 for (; pIt != pEnd; ++pIt ) 00146 { 00147 QString library = (*pIt).m_document.documentElement().attribute( "library" ); 00148 00149 if ( library.isEmpty() || hasPlugin( parent, library ) ) 00150 continue; 00151 00152 Plugin *plugin = loadPlugin( parent, library, (*pIt).m_document.documentElement().attribute( "X-KDE-PluginKeyword" ) ); 00153 00154 if ( plugin ) 00155 { 00156 plugin->d->m_parentInstance = componentData; 00157 plugin->setXMLFile( (*pIt).m_relXMLFileName, false, false ); 00158 plugin->setDOMDocument( (*pIt).m_document ); 00159 00160 } 00161 } 00162 00163 } 00164 00165 void Plugin::loadPlugins( QObject *parent, const QList<PluginInfo> &pluginInfos ) 00166 { 00167 loadPlugins(parent, pluginInfos, KComponentData()); 00168 } 00169 00170 // static, deprecated 00171 #ifndef KDE_NO_DEPRECATED 00172 Plugin* Plugin::loadPlugin( QObject * parent, const char* libname ) 00173 { 00174 Plugin* plugin = KLibLoader::createInstance<Plugin>( libname, parent ); 00175 if ( !plugin ) 00176 return 0; 00177 plugin->d->m_library = libname; 00178 return plugin; 00179 } 00180 #endif 00181 00182 // static, deprecated 00183 #ifndef KDE_NO_DEPRECATED 00184 Plugin* Plugin::loadPlugin( QObject * parent, const QByteArray &libname ) 00185 { 00186 return loadPlugin( parent, libname.data() ); 00187 } 00188 #endif 00189 00190 Plugin* Plugin::loadPlugin( QObject * parent, const QString &libname ) 00191 { 00192 return loadPlugin( parent, libname, "" ); 00193 } 00194 00195 // static 00196 Plugin* Plugin::loadPlugin( QObject * parent, const QString &libname, const QString &keyword ) 00197 { 00198 KPluginLoader loader( libname ); 00199 KPluginFactory* factory = loader.factory(); 00200 00201 if (!factory) { 00202 return 0; 00203 } 00204 00205 Plugin* plugin = factory->create<Plugin>( keyword, parent ); 00206 if ( !plugin ) 00207 return 0; 00208 plugin->d->m_library = libname; 00209 return plugin; 00210 } 00211 00212 QList<KParts::Plugin *> Plugin::pluginObjects( QObject *parent ) 00213 { 00214 QList<KParts::Plugin *> objects; 00215 00216 if (!parent ) 00217 return objects; 00218 00219 // TODO: move to a new method KGlobal::findDirectChildren, if there is more than one use of this? 00220 const QObjectList plugins = parent->children(); 00221 00222 QObjectList::ConstIterator it = plugins.begin(); 00223 for ( ; it != plugins.end() ; ++it ) 00224 { 00225 Plugin * plugin = qobject_cast<Plugin *>( *it ); 00226 if ( plugin ) 00227 objects.append( plugin ); 00228 } 00229 00230 return objects; 00231 } 00232 00233 bool Plugin::hasPlugin( QObject* parent, const QString& library ) 00234 { 00235 const QObjectList plugins = parent->children(); 00236 00237 QObjectList::ConstIterator it = plugins.begin(); 00238 for ( ; it != plugins.end() ; ++it ) 00239 { 00240 Plugin * plugin = qobject_cast<Plugin *>( *it ); 00241 if ( plugin && plugin->d->m_library == library ) 00242 { 00243 return true; 00244 } 00245 } 00246 return false; 00247 } 00248 00249 void Plugin::setComponentData(const KComponentData &componentData) 00250 { 00251 KGlobal::locale()->insertCatalog(componentData.catalogName()); 00252 KXMLGUIClient::setComponentData(componentData); 00253 } 00254 00255 void Plugin::loadPlugins(QObject *parent, KXMLGUIClient* parentGUIClient, 00256 const KComponentData &componentData, bool enableNewPluginsByDefault, 00257 int interfaceVersionRequired) 00258 { 00259 KConfigGroup cfgGroup( componentData.config(), "KParts Plugins" ); 00260 const QList<PluginInfo> plugins = pluginInfos( componentData ); 00261 QList<PluginInfo>::ConstIterator pIt = plugins.begin(); 00262 const QList<PluginInfo>::ConstIterator pEnd = plugins.end(); 00263 for (; pIt != pEnd; ++pIt ) 00264 { 00265 QDomElement docElem = (*pIt).m_document.documentElement(); 00266 QString library = docElem.attribute( "library" ); 00267 QString keyword; 00268 00269 if ( library.isEmpty() ) 00270 continue; 00271 00272 // Check configuration 00273 const QString name = docElem.attribute( "name" ); 00274 00275 bool pluginEnabled = enableNewPluginsByDefault; 00276 if ( cfgGroup.hasKey( name + "Enabled" ) ) 00277 { 00278 pluginEnabled = cfgGroup.readEntry( name + "Enabled" , false ); 00279 } 00280 else 00281 { // no user-setting, load plugin default setting 00282 QString relPath = QString( componentData.componentName() ) + '/' + (*pIt).m_relXMLFileName; 00283 relPath.truncate( relPath.lastIndexOf( '.' ) ); // remove extension 00284 relPath += ".desktop"; 00285 //kDebug(1000) << "looking for " << relPath; 00286 const QString desktopfile = componentData.dirs()->findResource( "data", relPath ); 00287 if( !desktopfile.isEmpty() ) 00288 { 00289 //kDebug(1000) << "loadPlugins found desktop file for " << name << ": " << desktopfile; 00290 KDesktopFile _desktop( desktopfile ); 00291 const KConfigGroup desktop = _desktop.desktopGroup(); 00292 keyword = desktop.readEntry("X-KDE-PluginKeyword", ""); 00293 pluginEnabled = desktop.readEntry( "X-KDE-PluginInfo-EnabledByDefault", 00294 enableNewPluginsByDefault ); 00295 if ( interfaceVersionRequired != 0 ) 00296 { 00297 const int version = desktop.readEntry( "X-KDE-InterfaceVersion", 1 ); 00298 if ( version != interfaceVersionRequired ) 00299 { 00300 kDebug(1000) << "Discarding plugin " << name << ", interface version " << version << ", expected " << interfaceVersionRequired; 00301 pluginEnabled = false; 00302 } 00303 } 00304 } 00305 else 00306 { 00307 //kDebug(1000) << "loadPlugins no desktop file found in " << relPath; 00308 } 00309 } 00310 00311 // search through already present plugins 00312 const QObjectList pluginList = parent->children(); 00313 00314 bool pluginFound = false; 00315 for ( QObjectList::ConstIterator it = pluginList.begin(); it != pluginList.end() ; ++it ) 00316 { 00317 Plugin * plugin = qobject_cast<Plugin *>( *it ); 00318 if( plugin && plugin->d->m_library == library ) 00319 { 00320 // delete and unload disabled plugins 00321 if( !pluginEnabled ) 00322 { 00323 kDebug( 1000 ) << "remove plugin " << name; 00324 KXMLGUIFactory * factory = plugin->factory(); 00325 if( factory ) 00326 factory->removeClient( plugin ); 00327 delete plugin; 00328 } 00329 00330 pluginFound = true; 00331 break; 00332 } 00333 } 00334 00335 // if the plugin is already loaded or if it's disabled in the 00336 // configuration do nothing 00337 if( pluginFound || !pluginEnabled ) 00338 continue; 00339 00340 kDebug( 1000 ) << "load plugin " << name << " " << library << " " << keyword; 00341 Plugin *plugin = loadPlugin( parent, library, keyword ); 00342 00343 if ( plugin ) 00344 { 00345 plugin->d->m_parentInstance = componentData; 00346 plugin->setXMLFile( (*pIt).m_relXMLFileName, false, false ); 00347 plugin->setDOMDocument( (*pIt).m_document ); 00348 parentGUIClient->insertChildClient( plugin ); 00349 } 00350 } 00351 } 00352 00353 // vim:sw=4:et:sts=4 00354 00355 #include "plugin.moc"
KDE 4.7 API Reference