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
00040
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
00120 unloadPlugins();
00121 }
00122
00123
00124 void PluginController::loadDefaultParts()
00125 {
00126
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
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
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
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
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
00175
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
00184
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
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
00213 if (!config.readBoolEntry( name, true)) {
00214
00215 KDevPlugin* part = m_parts[name];
00216 if( part ) {
00217 removePart( part );
00218
00219 m_parts.remove( name );
00220 part->deleteLater();
00221 }
00222 continue;
00223 }
00224
00225
00226
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
00237 m_parts.insert( name, plugin );
00238 integratePart( plugin );
00239 }
00240 }
00241 }
00242
00243
00244 void PluginController::unloadPlugins()
00245 {
00246
00247 for( QDictIterator<KDevPlugin> it( m_parts ); !it.isEmpty(); )
00248 {
00249 KDevPlugin* part = it.current();
00250 removePart( part );
00251
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
00268
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
00279 m_parts.insert( name, part );
00280 }
00281 }
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 void PluginController::unloadPlugins( QStringList const & unloadParts )
00298 {
00299 QStringList::ConstIterator it = unloadParts.begin();
00300 while ( it != unloadParts.end() )
00301 {
00302
00303 KDevPlugin* part = m_parts[ *it ];
00304 if( part )
00305 {
00306 removePart( part );
00307
00308 m_parts.remove( *it );
00309
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
00322 if( !langlist.isEmpty() && !langlist.contains(projectInfo->m_activeLanguage) ) {
00323 projectInfo->m_ignoreParts << service->name();
00324 return false;
00325 }
00326
00327
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
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
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
00403
00404
00405
00406
00407
00408
00409
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
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 #include "plugincontroller.moc"
00436
This file is part of the documentation for KDevelop Version 3.1.2.