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 // KDE4: 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 const QObjectList plugins = parent->children(); 00220 00221 QObjectList::ConstIterator it = plugins.begin(); 00222 for ( ; it != plugins.end() ; ++it ) 00223 { 00224 Plugin * plugin = qobject_cast<Plugin *>( *it ); 00225 if ( plugin ) 00226 objects.append( plugin ); 00227 } 00228 00229 return objects; 00230 } 00231 00232 bool Plugin::hasPlugin( QObject* parent, const QString& library ) 00233 { 00234 const QObjectList plugins = parent->children(); 00235 00236 QObjectList::ConstIterator it = plugins.begin(); 00237 for ( ; it != plugins.end() ; ++it ) 00238 { 00239 Plugin * plugin = qobject_cast<Plugin *>( *it ); 00240 if ( plugin && plugin->d->m_library == library ) 00241 { 00242 return true; 00243 } 00244 } 00245 return false; 00246 } 00247 00248 void Plugin::setComponentData(const KComponentData &componentData) 00249 { 00250 KGlobal::locale()->insertCatalog(componentData.catalogName()); 00251 KXMLGUIClient::setComponentData(componentData); 00252 } 00253 00254 void Plugin::loadPlugins(QObject *parent, KXMLGUIClient* parentGUIClient, 00255 const KComponentData &componentData, bool enableNewPluginsByDefault, 00256 int interfaceVersionRequired) 00257 { 00258 KConfigGroup cfgGroup( componentData.config(), "KParts Plugins" ); 00259 const QList<PluginInfo> plugins = pluginInfos( componentData ); 00260 QList<PluginInfo>::ConstIterator pIt = plugins.begin(); 00261 const QList<PluginInfo>::ConstIterator pEnd = plugins.end(); 00262 for (; pIt != pEnd; ++pIt ) 00263 { 00264 QDomElement docElem = (*pIt).m_document.documentElement(); 00265 QString library = docElem.attribute( "library" ); 00266 QString keyword; 00267 00268 if ( library.isEmpty() ) 00269 continue; 00270 00271 // Check configuration 00272 const QString name = docElem.attribute( "name" ); 00273 00274 bool pluginEnabled = enableNewPluginsByDefault; 00275 if ( cfgGroup.hasKey( name + "Enabled" ) ) 00276 { 00277 pluginEnabled = cfgGroup.readEntry( name + "Enabled" , false ); 00278 } 00279 else 00280 { // no user-setting, load plugin default setting 00281 QString relPath = QString( componentData.componentName() ) + '/' + (*pIt).m_relXMLFileName; 00282 relPath.truncate( relPath.lastIndexOf( '.' ) ); // remove extension 00283 relPath += ".desktop"; 00284 //kDebug(1000) << "looking for " << relPath; 00285 const QString desktopfile = componentData.dirs()->findResource( "data", relPath ); 00286 if( !desktopfile.isEmpty() ) 00287 { 00288 //kDebug(1000) << "loadPlugins found desktop file for " << name << ": " << desktopfile; 00289 KDesktopFile _desktop( desktopfile ); 00290 const KConfigGroup desktop = _desktop.desktopGroup(); 00291 keyword = desktop.readEntry("X-KDE-PluginKeyword", ""); 00292 pluginEnabled = desktop.readEntry( "X-KDE-PluginInfo-EnabledByDefault", 00293 enableNewPluginsByDefault ); 00294 if ( interfaceVersionRequired != 0 ) 00295 { 00296 const int version = desktop.readEntry( "X-KDE-InterfaceVersion", 1 ); 00297 if ( version != interfaceVersionRequired ) 00298 { 00299 kDebug(1000) << "Discarding plugin " << name << ", interface version " << version << ", expected " << interfaceVersionRequired; 00300 pluginEnabled = false; 00301 } 00302 } 00303 } 00304 else 00305 { 00306 //kDebug(1000) << "loadPlugins no desktop file found in " << relPath; 00307 } 00308 } 00309 00310 // search through already present plugins 00311 const QObjectList pluginList = parent->children(); 00312 00313 bool pluginFound = false; 00314 for ( QObjectList::ConstIterator it = pluginList.begin(); it != pluginList.end() ; ++it ) 00315 { 00316 Plugin * plugin = qobject_cast<Plugin *>( *it ); 00317 if( plugin && plugin->d->m_library == library ) 00318 { 00319 // delete and unload disabled plugins 00320 if( !pluginEnabled ) 00321 { 00322 kDebug( 1000 ) << "remove plugin " << name; 00323 KXMLGUIFactory * factory = plugin->factory(); 00324 if( factory ) 00325 factory->removeClient( plugin ); 00326 delete plugin; 00327 } 00328 00329 pluginFound = true; 00330 break; 00331 } 00332 } 00333 00334 // if the plugin is already loaded or if it's disabled in the 00335 // configuration do nothing 00336 if( pluginFound || !pluginEnabled ) 00337 continue; 00338 00339 kDebug( 1000 ) << "load plugin " << name << " " << library << " " << keyword; 00340 Plugin *plugin = loadPlugin( parent, library, keyword ); 00341 00342 if ( plugin ) 00343 { 00344 plugin->d->m_parentInstance = componentData; 00345 plugin->setXMLFile( (*pIt).m_relXMLFileName, false, false ); 00346 plugin->setDOMDocument( (*pIt).m_document ); 00347 parentGUIClient->insertChildClient( plugin ); 00348 } 00349 } 00350 } 00351 00352 // vim:sw=4:et:sts=4 00353 00354 #include "plugin.moc"
KDE 4.6 API Reference