KDevelop API Documentation

plugincontroller.cpp

Go to the documentation of this file.
00001 #include <qfile.h>
00002 #include <qvbox.h>
00003 
00004 #include <kcmdlineargs.h>
00005 #include <kapplication.h>
00006 #include <klibloader.h>
00007 #include <kservice.h>
00008 #include <ktrader.h>
00009 #include <kmessagebox.h>
00010 #include <kconfig.h>
00011 #include <klocale.h>
00012 #include <kmainwindow.h>
00013 #include <kparts/componentfactory.h>
00014 #include <assert.h>
00015 #include <kdebug.h>
00016 #include <kdialogbase.h>
00017 #include <kcmdlineargs.h>
00018 #include <kstandarddirs.h>
00019 #include <kstatusbar.h>
00020 #include <kiconloader.h>
00021 
00022 #include <kdevapi.h>
00023 #include <kdevplugin.h>
00024 #include <kdevmakefrontend.h>
00025 #include <kdevappfrontend.h>
00026 #include <kdevdifffrontend.h>
00027 #include <kdevsourceformatter.h>
00028 #include <kdevcreatefile.h>
00029 #include <kaction.h>
00030 
00031 #include "core.h"
00032 #include "api.h"
00033 #include "toplevel.h"
00034 #include "projectmanager.h"
00035 #include "partselectwidget.h"
00036 
00037 #include "plugincontroller.h"
00038 
00039 // a separate method in this anonymous namespace to avoid having it all
00040 // inline in plugincontroller.h
00041 namespace
00042 {
00043   template <class ComponentType>
00044   ComponentType *loadDefaultPart( const QString &serviceType )
00045   {
00046     KTrader::OfferList offers = KTrader::self()->query(serviceType, QString("[X-KDevelop-Version] == %1").arg(KDEVELOP_PLUGIN_VERSION));
00047     KTrader::OfferList::ConstIterator serviceIt = offers.begin();
00048     for ( ; serviceIt != offers.end(); ++serviceIt ) {
00049       KService::Ptr service = *serviceIt;
00050 
00051       ComponentType *part = KParts::ComponentFactory
00052         ::createInstanceFromService< ComponentType >( service, API::getInstance(), 0,
00053                                                       PluginController::argumentsFromService( service ) );
00054 
00055       if ( part )
00056         return part;
00057     }
00058     return 0;
00059   }
00060 }
00061 
00062 PluginController *PluginController::s_instance = 0;
00063 
00064 
00065 PluginController *PluginController::getInstance()
00066 {
00067   if (!s_instance)
00068     s_instance = new PluginController();
00069   return s_instance;
00070 }
00071 
00072 
00073 PluginController::PluginController()
00074   : QObject()
00075 {
00076   connect( Core::getInstance(), SIGNAL(configWidget(KDialogBase*)),
00077            this, SLOT(slotConfigWidget(KDialogBase*)) );
00078   
00079   m_defaultProfile = QString::fromLatin1( "FullIDE" );
00080   m_defaultProfilePath = kapp->dirs()->localkdedir() + "/" + 
00081              KStandardDirs::kde_default( "data" ) + 
00082              QString::fromLatin1("/kdevelop/profiles/FullIDE");
00083 }
00084 
00085 
00086 void PluginController::loadInitialPlugins()
00087 {
00088     KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
00089 
00090     if (TopLevel::mode != TopLevel::AssistantMode)
00091         loadDefaultParts();
00092     loadCorePlugins();
00093     
00094     m_profile = QString::null;
00095     if( args->isSet("profile") ){
00096     m_profile = QString::fromLocal8Bit( args->getOption("profile") );
00097     m_profilePath = m_profile;
00098     
00099     if( m_profile[0] != '/' )
00100         m_profilePath = locate( "data", QString::fromLatin1("kdevelop/profiles/") + m_profile );
00101     
00102     if( m_profilePath.isEmpty() )
00103         m_profilePath = kapp->dirs()->localkdedir() +
00104                 KStandardDirs::kde_default( "data" ) + 
00105                 QString::fromLatin1("/kdevelop/profiles/") + m_profile;
00106     }
00107     
00108     if( m_profile.isEmpty() || m_profilePath.isEmpty() ){
00109     m_profile = m_defaultProfile;
00110     m_profilePath = m_defaultProfilePath;
00111     }
00112     
00113     loadGlobalPlugins();
00114 }
00115 
00116 
00117 PluginController::~PluginController()
00118 {
00119 //  unloadGlobalPlugins();
00120   unloadPlugins();
00121 }
00122 
00123 
00124 void PluginController::loadDefaultParts()
00125 {
00126   // Make frontend
00127   emit loadingPlugin(i18n("Loading: Make frontend"));
00128   KDevMakeFrontend *makeFrontend = loadDefaultPart< KDevMakeFrontend >( "KDevelop/MakeFrontend" );
00129   if ( makeFrontend ) {
00130     API::getInstance()->setMakeFrontend( makeFrontend );
00131     integratePart( makeFrontend );
00132   }
00133 
00134   // App frontend
00135   emit loadingPlugin(i18n("Loading: Application frontend"));
00136   KDevAppFrontend *appFrontend = loadDefaultPart< KDevAppFrontend >( "KDevelop/AppFrontend" );
00137   if ( appFrontend ) {
00138     API::getInstance()->setAppFrontend( appFrontend );
00139     integratePart( appFrontend );
00140   }
00141 
00142   // Diff frontend
00143   emit loadingPlugin(i18n("Loading: Diff frontend"));
00144   KDevDiffFrontend *diffFrontend = loadDefaultPart< KDevDiffFrontend >( "KDevelop/DiffFrontend" );
00145   if ( diffFrontend ) {
00146     API::getInstance()->setDiffFrontend( diffFrontend );
00147     integratePart( diffFrontend );
00148   } else {
00149     kdDebug( 9000 ) << "could not load Diff frontend" << endl;
00150   }
00151 
00152   // Source formatter
00153   emit loadingPlugin(i18n("Loading: Source formatter"));
00154   KDevSourceFormatter *sourceFormatter = loadDefaultPart< KDevSourceFormatter >( "KDevelop/SourceFormatter" );
00155   if ( sourceFormatter ) {
00156     API::getInstance()->setSourceFormatter( sourceFormatter );
00157     integratePart( sourceFormatter );
00158   } else {
00159     kdDebug( 9000 ) << "could not load Source formatter" << endl;
00160   }
00161   
00162   // File Create
00163   emit loadingPlugin( i18n("Loading: File Create") );
00164   KDevCreateFile * createFile = loadDefaultPart<KDevCreateFile>( "KDevelop/CreateFile" );
00165   if ( createFile ) {
00166     API::getInstance()->setCreateFile( createFile );
00167     integratePart( createFile );
00168   } else {
00169     kdDebug( 9000 ) << "Could not load CreateFile plugin" << endl;
00170   }
00171   
00172 }
00173 
00174 // a Core plugin is implicitly global, so it makes
00175 // sense to put them in the global plugin container
00176 void PluginController::loadCorePlugins()
00177 {
00178   KTrader::OfferList coreOffers = pluginServices( "Core" );
00179   for (KTrader::OfferList::ConstIterator it = coreOffers.begin(); it != coreOffers.end(); ++it)
00180   {
00181     QString name = (*it)->name();
00182 
00183     // Check if it is already loaded
00184 //    if( m_globalParts[ name ] != 0 )
00185     if( m_parts[ name ] != 0 )
00186       continue;
00187 
00188     assert( !( *it )->hasServiceType( "KDevelop/Part" ) );
00189 
00190     emit loadingPlugin(i18n("Loading: %1").arg((*it)->genericName()));
00191 
00192     KDevPlugin *plugin = loadPlugin( *it );
00193     if ( plugin )
00194     {
00195 //        m_globalParts.insert( name, plugin );
00196         m_parts.insert( name, plugin );
00197         integratePart( plugin );
00198     }
00199   }
00200 }
00201 
00202 void PluginController::loadGlobalPlugins()
00203 {
00204   KTrader::OfferList globalOffers = pluginServices( "Global" );
00205   KConfig config( m_profilePath );
00206   for (KTrader::OfferList::ConstIterator it = globalOffers.begin(); it != globalOffers.end(); ++it)
00207   {
00208     config.setGroup( "Plugins" );
00209 
00210     QString name = (*it)->name();
00211 
00212     // Unload it if is marked as ignored and loaded
00213     if (!config.readBoolEntry( name, true)) {
00214 //      KDevPlugin* part = m_globalParts[name];
00215       KDevPlugin* part = m_parts[name];
00216       if( part ) {
00217         removePart( part );
00218 //        m_globalParts.remove( name );
00219         m_parts.remove( name );
00220         part->deleteLater();
00221       }
00222       continue;
00223     }
00224 
00225     // Check if it is already loaded
00226 //    if( m_globalParts[ name ] != 0 )
00227     if( m_parts[ name ] != 0 )
00228       continue;
00229 
00230     assert( !( *it )->hasServiceType( "KDevelop/Part" ) );
00231 
00232     emit loadingPlugin(i18n("Loading: %1").arg((*it)->genericName()));
00233 
00234     KDevPlugin *plugin = loadPlugin( *it );
00235     if ( plugin ) {
00236 //  m_globalParts.insert( name, plugin );
00237     m_parts.insert( name, plugin );
00238     integratePart( plugin );
00239     }
00240   }
00241 }
00242 
00243 //void PluginController::unloadGlobalPlugins()
00244 void PluginController::unloadPlugins()
00245 {
00246 //  for( QDictIterator<KDevPlugin> it( m_globalParts ); !it.isEmpty(); )
00247   for( QDictIterator<KDevPlugin> it( m_parts ); !it.isEmpty(); )
00248   {
00249     KDevPlugin* part = it.current();
00250     removePart( part );
00251 //    m_globalParts.remove( it.currentKey() );
00252     m_parts.remove( it.currentKey() );
00253     delete part;
00254   }
00255 }
00256 
00257 void PluginController::loadLocalParts( ProjectInfo * projectInfo, QStringList const & loadPlugins, QStringList const & ignorePlugins  )
00258 {
00259     KTrader::OfferList localOffers = pluginServices( "Project" );
00260     for (KTrader::OfferList::ConstIterator it = localOffers.begin(); it != localOffers.end(); ++it)
00261     {
00262         QString name = (*it)->name();
00263         TopLevel::getInstance()->statusBar()->message( i18n("Loading: %1").arg( (*it)->genericName() ) );
00264         
00265         kdDebug(9000) << "-----------------------------> load part " << name << endl;
00266         
00267         // Check if it is already loaded or should be ignored
00268 //      if( m_localParts[ name ] != 0 || ignorePlugins.contains( name ) )
00269         if( m_parts[ name ] != 0 || ignorePlugins.contains( name ) )
00270             continue;
00271     
00272         if( loadPlugins.contains( name ) || checkNewService( projectInfo, *it ) )
00273         {
00274             KDevPlugin *part = loadPlugin( *it );
00275             if ( !part ) continue;
00276         
00277             integratePart( part );
00278 //          m_localParts.insert( name, part );
00279             m_parts.insert( name, part );
00280         }
00281     }
00282 }
00283 /*
00284 void PluginController::unloadAllLocalParts( )
00285 {
00286     for( QDictIterator<KDevPlugin> it(m_localParts); !it.isEmpty(); )
00287     {
00288         KDevPlugin* part = it.current();
00289         removePart( part );
00290         m_localParts.remove( it.currentKey() );
00291         delete part;
00292     }
00293 }
00294 */
00295 
00296 //void PluginController::unloadLocalParts( QStringList const & unloadParts )
00297 void PluginController::unloadPlugins( QStringList const & unloadParts )
00298 {
00299     QStringList::ConstIterator it = unloadParts.begin();
00300     while ( it != unloadParts.end() )
00301     {
00302 //      KDevPlugin* part = m_localParts[ *it ];
00303         KDevPlugin* part = m_parts[ *it ];
00304         if( part ) 
00305         {
00306             removePart( part );
00307 //          m_localParts.remove( *it );
00308             m_parts.remove( *it );
00309 //          part->deleteLater();
00310             delete part;
00311         }
00312         ++it;
00313     }
00314 }
00315 
00316 bool PluginController::checkNewService( ProjectInfo * projectInfo, const KService::Ptr &service )
00317 {
00318   QVariant var = service->property("X-KDevelop-ProgrammingLanguages");
00319   QStringList langlist = var.asStringList();
00320 
00321   // empty means it supports all languages
00322   if( !langlist.isEmpty() && !langlist.contains(projectInfo->m_activeLanguage) ) {
00323     projectInfo->m_ignoreParts << service->name();
00324     return false;
00325   }
00326 
00327   // the language is ok, now check if the keywords match
00328   QStringList serviceKeywords = service->keywords();
00329   for ( QStringList::Iterator is = serviceKeywords.begin();
00330         is != serviceKeywords.end(); ++is )
00331   {
00332     if ( !projectInfo->m_keywords.contains(*is) ) {
00333       // no match
00334       kdDebug(9000) << "ignoreParts because Keyword does not match: " << service->name() << endl;
00335       projectInfo->m_ignoreParts << service->name();
00336       return false;
00337     }
00338   }
00339 
00340   projectInfo->m_loadParts << service->name();
00341   return true;
00342 }
00343 
00344 KService::List PluginController::pluginServices( const QString &scope )
00345 {
00346     QString constraint = QString::fromLatin1("[X-KDevelop-Version] == %1").arg(KDEVELOP_PLUGIN_VERSION);
00347 
00348     if ( !scope.isEmpty() )
00349     constraint += QString::fromLatin1( " and [X-KDevelop-Scope] == '%1'").arg( scope );
00350     if (TopLevel::mode == TopLevel::AssistantMode)
00351         constraint += QString::fromLatin1( " and [X-KDevelop-Mode] == 'AssistantMode'");
00352     return KTrader::self()->query( QString::fromLatin1( "KDevelop/Plugin" ),
00353                                constraint );
00354 }
00355 
00356 KDevPlugin *PluginController::loadPlugin( const KService::Ptr &service )
00357 {
00358     return KParts::ComponentFactory
00359         ::createInstanceFromService<KDevPlugin>( service, API::getInstance(), 0,
00360                                                  argumentsFromService( service ) );
00361 }
00362 
00363 QStringList PluginController::argumentsFromService( const KService::Ptr &service )
00364 {
00365     QStringList args;
00366     if ( !service ) 
00367         // service is a reference to a pointer, so a check whether it is 0 is still required
00368         return args;
00369     QVariant prop = service->property( "X-KDevelop-Args" );
00370     if ( prop.isValid() )
00371         args = QStringList::split( " ", prop.toString() );
00372     return args;
00373 }
00374 
00375 void PluginController::slotConfigWidget( KDialogBase* dlg )
00376 {
00377     QVBox *vbox = dlg->addVBoxPage( i18n("Plugins"), i18n("Plugins"), DesktopIcon("kdf") );
00378   PartSelectWidget *w = new PartSelectWidget(vbox, "part selection widget");
00379   connect( dlg, SIGNAL(okClicked()), w, SLOT(accept()) );
00380   connect( w, SIGNAL(accepted()), this, SLOT(loadGlobalPlugins()) );
00381 }
00382 
00383 void PluginController::integratePart(KXMLGUIClient *part)
00384 {
00385     if ( ! part ) return;
00386 
00387     TopLevel::getInstance()->main()->guiFactory()->addClient(part);
00388 
00389     connect( part->actionCollection(), SIGNAL( actionStatusText( const QString & ) ),
00390         TopLevel::getInstance()->main()->actionCollection(), SIGNAL( actionStatusText( const QString & ) ) );
00391 }
00392 
00393 void PluginController::removePart(KXMLGUIClient *part)
00394 {
00395   TopLevel::getInstance()->main()->guiFactory()->removeClient(part);
00396 }
00397 
00398 const QValueList<KDevPlugin*> PluginController::loadedPlugins()
00399 {
00400     QValueList<KDevPlugin*> plugins;
00401 /*
00402     QDictIterator<KDevPlugin> it(m_localParts);
00403     while( it.current() )
00404     {
00405         plugins.append( it.current() );
00406         ++it;
00407     }
00408 */
00409 //  QDictIterator<KDevPlugin> itt(m_globalParts);
00410     QDictIterator<KDevPlugin> itt(m_parts);
00411     while( itt.current() )
00412     {
00413         plugins.append( itt.current() );
00414         ++itt;
00415     }
00416 
00417     return plugins;
00418 }
00419 /*
00420 KDevPlugin * PluginController::getPlugin( const KService::Ptr & service )
00421 {
00422     KDevPlugin * plugin = m_parts[ (*it)->name() ];
00423     if ( !plugin )
00424     {
00425         KDevPlugin * plugin = loadPlugin( *it );
00426         if ( plugin )
00427         {
00428             integratePart( plugin );
00429             m_parts.insert( (*it)->name(), plugin );
00430         }
00431     }
00432     return plugin;
00433 }
00434 */
00435 #include "plugincontroller.moc"
00436 
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:43 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003