00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00024 #include <qstringlist.h>
00025
00026 #include <ktrader.h>
00027 #include <kparts/componentfactory.h>
00028 #include <kdebug.h>
00029 #include <kdialog.h>
00030
00031 #include "plugin.h"
00032 #include "pluginloader.h"
00033 #include "interface.h"
00034 #include <kconfig.h>
00035 #include <qcheckbox.h>
00036 #include <qlayout.h>
00037
00107 namespace KIPI {
00108
00109
00110
00111
00112
00113
00114 struct PluginLoader::Info::Private {
00115 QString m_name;
00116 QString m_comment;
00117 QString m_library;
00118 Plugin* m_plugin;
00119 bool m_shouldLoad;
00120 };
00121
00122
00123 PluginLoader::Info::Info(const QString& name, const QString& comment, const QString& library, bool shouldLoad)
00124 {
00125 d=new Private;
00126 d->m_name=name;
00127 d->m_comment=comment;
00128 d->m_library=library;
00129 d->m_plugin=0;
00130 d->m_shouldLoad=shouldLoad;
00131 }
00132
00133
00134 PluginLoader::Info::~Info()
00135 {
00136 delete d;
00137 }
00138
00139
00140 QString PluginLoader::Info::name() const
00141 {
00142 return d->m_name;
00143 }
00144
00145
00146 QString PluginLoader::Info::comment() const
00147 {
00148 return d->m_comment;
00149 }
00150
00151
00152 QString PluginLoader::Info::library() const
00153 {
00154 return d->m_library;
00155 }
00156
00157
00158 Plugin* PluginLoader::Info::plugin() const
00159 {
00160 return d->m_plugin;
00161 }
00162
00163
00164 void PluginLoader::Info::setPlugin(Plugin* plugin)
00165 {
00166 d->m_plugin=plugin;
00167 }
00168
00169
00170 bool PluginLoader::Info::shouldLoad() const
00171 {
00172 return d->m_shouldLoad;
00173 }
00174
00175
00176 void PluginLoader::Info::setShouldLoad(bool value)
00177 {
00178 d->m_shouldLoad=value;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187 static PluginLoader* s_instance = 0;
00188
00189
00190 struct PluginLoader::Private
00191 {
00192 PluginList m_pluginList;
00193 Interface* m_interface;
00194 QStringList m_ignores;
00195 };
00196
00197
00198 PluginLoader::PluginLoader( const QStringList& ignores, Interface* interface )
00199 {
00200 Q_ASSERT( s_instance == 0 );
00201 s_instance = this;
00202
00203 d=new Private;
00204 d->m_interface = interface;
00205 d->m_ignores = ignores;
00206
00207 KTrader::OfferList offers = KTrader::self()->query("KIPI/Plugin");
00208 KConfig* config = KGlobal::config();
00209 config->setGroup( QString::fromLatin1( "KIPI/EnabledPlugin" ) );
00210
00211 KTrader::OfferList::ConstIterator iter;
00212 for(iter = offers.begin(); iter != offers.end(); ++iter) {
00213
00214 KService::Ptr service = *iter;
00215 QString name = service->name();
00216 QString comment = service->comment();
00217 QString library = service->library();
00218 QStringList reqFeatures = service->property( QString::fromLatin1( "X-KIPI-ReqFeatures" ) ).toStringList();
00219
00220 if (library.isEmpty() || name.isEmpty() ) {
00221 kdWarning( 51001 ) << "KIPI::PluginLoader: Plugin had an empty name or library file - this should not happen." << endl;
00222 continue;
00223 }
00224
00225 if ( d->m_ignores.contains( name ) ) {
00226 kdDebug( 51001 ) << "KIPI::PluginLoader: plugin " << name << " is in the ignore list for host application" << endl;
00227 continue;
00228 }
00229
00230 bool appHasAllReqFeatures=true;
00231 for( QStringList::Iterator featureIt = reqFeatures.begin(); featureIt != reqFeatures.end(); ++featureIt ) {
00232 if ( !d->m_interface->hasFeature( *featureIt ) ) {
00233 kdDebug( 51001 ) << "Plugin " << name << " was not loaded because the host application is missing\n"
00234 << "the feature " << *featureIt << endl;
00235 appHasAllReqFeatures=false;
00236 break;
00237 }
00238 }
00239
00240 bool load = config->readBoolEntry( name, true );
00241
00242 if (!appHasAllReqFeatures)
00243 continue;
00244
00245 Info* info = new Info( name, comment, library, load );
00246 d->m_pluginList.append( info );
00247 }
00248 }
00249
00250 PluginLoader::~PluginLoader()
00251 {
00252 delete d;
00253 }
00254
00255 void PluginLoader::loadPlugins()
00256 {
00257 for( PluginList::Iterator it = d->m_pluginList.begin(); it != d->m_pluginList.end(); ++it ) {
00258 loadPlugin( *it );
00259 }
00260 emit replug();
00261 }
00262
00263 void PluginLoader::loadPlugin( Info* info )
00264 {
00265 if ( info->plugin() == 0 && info->shouldLoad() ) {
00266 Plugin *plugin = 0;
00267 int error;
00268 plugin = KParts::ComponentFactory
00269 ::createInstanceFromLibrary<Plugin>(info->library().local8Bit().data(),
00270 d->m_interface, 0, QStringList(), &error);
00271
00272 if (plugin)
00273 kdDebug( 51001 ) << "KIPI::PluginLoader: Loaded plugin " << plugin->name()<< endl;
00274 else
00275 {
00276 kdWarning( 51001 ) << "KIPI::PluginLoader:: createInstanceFromLibrary returned 0 for "
00277 << info->name()
00278 << " (" << info->library() << ")"
00279 << " with error number "
00280 << error << endl;
00281 if (error == KParts::ComponentFactory::ErrNoLibrary)
00282 kdWarning( 51001 ) << "KLibLoader says: "
00283 << KLibLoader::self()->lastErrorMessage() << endl;
00284 }
00285 info->setPlugin(plugin);
00286 }
00287 if ( info->plugin() )
00288 emit PluginLoader::instance()->plug( info );
00289 }
00290
00291
00292 const PluginLoader::PluginList& PluginLoader::pluginList()
00293 {
00294 return d->m_pluginList;
00295 }
00296
00297 PluginLoader* PluginLoader::instance()
00298 {
00299 Q_ASSERT( s_instance != 0);
00300 return s_instance;
00301 }
00302
00303
00304
00305
00306
00307
00308
00309 ConfigWidget* PluginLoader::configWidget( QWidget* parent )
00310 {
00311 return new ConfigWidget( parent );
00312 }
00313
00314
00315 class PluginCheckBox :public QCheckBox
00316 {
00317 public:
00318 PluginCheckBox( PluginLoader::Info* info, QWidget* parent )
00319 : QCheckBox( info->comment(), parent ), info( info )
00320 {
00321 setChecked( info->shouldLoad() );
00322 }
00323 PluginLoader::Info* info;
00324 };
00325
00326
00327 struct ConfigWidget::Private
00328 {
00329 QValueList< PluginCheckBox* > _boxes;
00330 };
00331
00332
00333 ConfigWidget::ConfigWidget( QWidget* parent )
00334 :QScrollView( parent, "KIPI::PluginLoader::ConfigWidget" )
00335 {
00336 d=new Private;
00337 QWidget* top = new QWidget( viewport() );
00338 addChild( top );
00339 setResizePolicy( AutoOneFit );
00340
00341 QVBoxLayout* lay = new QVBoxLayout( top, KDialog::marginHint(), KDialog::spacingHint() );
00342
00343 PluginLoader::PluginList list = PluginLoader::instance()->d->m_pluginList;
00344 for( PluginLoader::PluginList::Iterator it = list.begin(); it != list.end(); ++it ) {
00345 PluginCheckBox* cb = new PluginCheckBox( *it, top );
00346 lay->addWidget( cb );
00347 d->_boxes.append( cb );
00348 }
00349
00350 lay->addStretch(10);
00351 }
00352
00353
00354 ConfigWidget::~ConfigWidget()
00355 {
00356 delete d;
00357 }
00358
00359
00360 void ConfigWidget::apply()
00361 {
00362 KConfig* config = KGlobal::config();
00363 config->setGroup( QString::fromLatin1( "KIPI/EnabledPlugin" ) );
00364 bool changes = false;
00365
00366 for( QValueList<PluginCheckBox*>::Iterator it = d->_boxes.begin(); it != d->_boxes.end(); ++it ) {
00367 bool orig = (*it)->info->shouldLoad();
00368 bool load = (*it)->isChecked();
00369 if ( orig != load ) {
00370 changes = true;
00371 config->writeEntry( (*it)->info->name(), load );
00372 (*it)->info->setShouldLoad(load);
00373 if ( load ) {
00374 PluginLoader::instance()->loadPlugin( (*it)->info);
00375 }
00376 else {
00377 if ( (*it)->info->plugin() )
00378 emit PluginLoader::instance()->unplug( (*it)->info);
00379 }
00380 }
00381 }
00382 emit PluginLoader::instance()->replug();
00383 }
00384
00385
00386 }
00387
00388 #include "pluginloader.moc"