pluginloader.cpp

Go to the documentation of this file.
00001 /* ============================================================
00002  * File  : pluginloader.cpp
00003  * Author: Renchi Raju <renchi@pooh.tam.uiuc.edu>
00004  * Date  : 2004-02-19
00005  * Description :
00006  *
00007  * Copyright 2004 by Renchi Raju
00008 
00009  * This program is free software; you can redistribute it
00010  * and/or modify it under the terms of the GNU Library General
00011  * Public License as published by the Free Software Foundation;
00012  * either version 2, or (at your option)
00013  * any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU Library General Public License for more details.
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 // PluginLoader::Info
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 // PluginLoader
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() ) // Do not emit if we had trouble loading the 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 // ConfigWidget
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() ) // Do not emit if we had trouble loading plugin.
00378                     emit PluginLoader::instance()->unplug( (*it)->info);
00379             }
00380         }
00381     }
00382     emit PluginLoader::instance()->replug();
00383 }
00384 
00385 
00386 } // namespace
00387 
00388 #include "pluginloader.moc"

Generated on Mon Nov 27 23:42:22 2006 for libKipi by  doxygen 1.5.0