forked from qt-creator/qt-creator
PluginManager: Behave more like a package manager
Instead of implicitly disabling plugins if their dependencies are disabled, implicitly enable plugins if some enabled plugin needs it. That will avoid issues if people disable plugins (e.g. QmlJSTools et al) and we later add one of these as a dependency to another plugin (e.g. make QmakeProjectManager depend on QmlJSTools), which resulted in the previously enabled plugin being implicitly disabled. Enabling a plugin in About Plugins now asks for all required dependencies to be enabled as well. Disabling a plugin in About Plugins now asks for disabling all plugins that require it. Using the -noload command line option now disables all plugins that require it in addition. Using the -load command line option now implicitly enables all plugins that are required. Multiple -noload and -load options are handled in the order given on the command line. Task-number: QTCREATORBUG-9131 Change-Id: I0956106105060a7898a8992e0629009d5ec3ea4d Reviewed-by: Daniel Teske <daniel.teske@theqtcompany.com>
This commit is contained in:
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
#include "optionsparser.h"
|
#include "optionsparser.h"
|
||||||
|
|
||||||
|
#include "pluginmanager.h"
|
||||||
|
#include "pluginmanager_p.h"
|
||||||
#include "pluginspec_p.h"
|
#include "pluginspec_p.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
@@ -173,6 +175,9 @@ bool OptionsParser::checkForNoLoadOption()
|
|||||||
m_hasError = true;
|
m_hasError = true;
|
||||||
} else {
|
} else {
|
||||||
spec->d->setForceDisabled(true);
|
spec->d->setForceDisabled(true);
|
||||||
|
// recursively disable all plugins that require this plugin
|
||||||
|
foreach (PluginSpec *dependantSpec, PluginManager::pluginsRequiringPlugin(spec))
|
||||||
|
dependantSpec->d->setForceDisabled(true);
|
||||||
m_isDependencyRefreshNeeded = true;
|
m_isDependencyRefreshNeeded = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -31,14 +31,14 @@
|
|||||||
#ifndef OPTIONSPARSER_H
|
#ifndef OPTIONSPARSER_H
|
||||||
#define OPTIONSPARSER_H
|
#define OPTIONSPARSER_H
|
||||||
|
|
||||||
#include "pluginmanager_p.h"
|
|
||||||
|
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
namespace ExtensionSystem {
|
namespace ExtensionSystem {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
class PluginManagerPrivate;
|
||||||
|
|
||||||
class OptionsParser
|
class OptionsParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@@ -48,7 +48,7 @@ PluginErrorOverview::PluginErrorOverview(QWidget *parent) :
|
|||||||
|
|
||||||
foreach (PluginSpec *spec, PluginManager::plugins()) {
|
foreach (PluginSpec *spec, PluginManager::plugins()) {
|
||||||
// only show errors on startup if plugin is enabled.
|
// only show errors on startup if plugin is enabled.
|
||||||
if (spec->hasError() && spec->isEnabledBySettings() && !spec->isDisabledIndirectly()) {
|
if (spec->hasError() && spec->isEffectivelyEnabled()) {
|
||||||
QListWidgetItem *item = new QListWidgetItem(spec->name());
|
QListWidgetItem *item = new QListWidgetItem(spec->name());
|
||||||
item->setData(Qt::UserRole, qVariantFromValue(spec));
|
item->setData(Qt::UserRole, qVariantFromValue(spec));
|
||||||
m_ui->pluginList->addItem(item);
|
m_ui->pluginList->addItem(item);
|
||||||
|
@@ -376,12 +376,62 @@ bool PluginManager::hasError()
|
|||||||
{
|
{
|
||||||
foreach (PluginSpec *spec, plugins()) {
|
foreach (PluginSpec *spec, plugins()) {
|
||||||
// only show errors on startup if plugin is enabled.
|
// only show errors on startup if plugin is enabled.
|
||||||
if (spec->hasError() && spec->isEnabledBySettings() && !spec->isDisabledIndirectly())
|
if (spec->hasError() && spec->isEffectivelyEnabled())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns all plugins that require \a spec to be loaded. Recurses into dependencies.
|
||||||
|
*/
|
||||||
|
QSet<PluginSpec *> PluginManager::pluginsRequiringPlugin(PluginSpec *spec)
|
||||||
|
{
|
||||||
|
QSet<PluginSpec *> dependingPlugins;
|
||||||
|
dependingPlugins.insert(spec);
|
||||||
|
foreach (PluginSpec *checkSpec, d->loadQueue()) {
|
||||||
|
QHashIterator<PluginDependency, PluginSpec *> depIt(checkSpec->dependencySpecs());
|
||||||
|
while (depIt.hasNext()) {
|
||||||
|
depIt.next();
|
||||||
|
if (depIt.key().type != PluginDependency::Required)
|
||||||
|
continue;
|
||||||
|
if (dependingPlugins.contains(depIt.value())) {
|
||||||
|
dependingPlugins.insert(checkSpec);
|
||||||
|
break; // no use to check other dependencies, continue with load queue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dependingPlugins.remove(spec);
|
||||||
|
return dependingPlugins;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns all plugins that \a spec requires to be loaded. Recurses into dependencies.
|
||||||
|
*/
|
||||||
|
QSet<PluginSpec *> PluginManager::pluginsRequiredByPlugin(PluginSpec *spec)
|
||||||
|
{
|
||||||
|
QSet<PluginSpec *> recursiveDependencies;
|
||||||
|
recursiveDependencies.insert(spec);
|
||||||
|
QList<PluginSpec *> queue;
|
||||||
|
queue.append(spec);
|
||||||
|
while (!queue.isEmpty()) {
|
||||||
|
PluginSpec *checkSpec = queue.takeFirst();
|
||||||
|
QHashIterator<PluginDependency, PluginSpec *> depIt(checkSpec->dependencySpecs());
|
||||||
|
while (depIt.hasNext()) {
|
||||||
|
depIt.next();
|
||||||
|
if (depIt.key().type != PluginDependency::Required)
|
||||||
|
continue;
|
||||||
|
PluginSpec *depSpec = depIt.value();
|
||||||
|
if (!recursiveDependencies.contains(depSpec)) {
|
||||||
|
recursiveDependencies.insert(depSpec);
|
||||||
|
queue.append(depSpec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
recursiveDependencies.remove(spec);
|
||||||
|
return recursiveDependencies;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Shuts down and deletes all plugins.
|
Shuts down and deletes all plugins.
|
||||||
*/
|
*/
|
||||||
@@ -647,10 +697,10 @@ static inline void formatOption(QTextStream &str,
|
|||||||
void PluginManager::formatOptions(QTextStream &str, int optionIndentation, int descriptionIndentation)
|
void PluginManager::formatOptions(QTextStream &str, int optionIndentation, int descriptionIndentation)
|
||||||
{
|
{
|
||||||
formatOption(str, QLatin1String(OptionsParser::LOAD_OPTION),
|
formatOption(str, QLatin1String(OptionsParser::LOAD_OPTION),
|
||||||
QLatin1String("plugin"), QLatin1String("Load <plugin>"),
|
QLatin1String("plugin"), QLatin1String("Load <plugin> and all plugins that it requires"),
|
||||||
optionIndentation, descriptionIndentation);
|
optionIndentation, descriptionIndentation);
|
||||||
formatOption(str, QLatin1String(OptionsParser::NO_LOAD_OPTION),
|
formatOption(str, QLatin1String(OptionsParser::NO_LOAD_OPTION),
|
||||||
QLatin1String("plugin"), QLatin1String("Do not load <plugin>"),
|
QLatin1String("plugin"), QLatin1String("Do not load <plugin> and all plugins that require it"),
|
||||||
optionIndentation, descriptionIndentation);
|
optionIndentation, descriptionIndentation);
|
||||||
formatOption(str, QLatin1String(OptionsParser::PROFILE_OPTION),
|
formatOption(str, QLatin1String(OptionsParser::PROFILE_OPTION),
|
||||||
QString(), QLatin1String("Profile plugin loading"),
|
QString(), QLatin1String("Profile plugin loading"),
|
||||||
@@ -1422,11 +1472,15 @@ void PluginManagerPrivate::readPluginPaths()
|
|||||||
void PluginManagerPrivate::resolveDependencies()
|
void PluginManagerPrivate::resolveDependencies()
|
||||||
{
|
{
|
||||||
foreach (PluginSpec *spec, pluginSpecs) {
|
foreach (PluginSpec *spec, pluginSpecs) {
|
||||||
|
spec->d->enabledIndirectly = false; // reset, is recalculated below
|
||||||
spec->d->resolveDependencies(pluginSpecs);
|
spec->d->resolveDependencies(pluginSpecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (PluginSpec *spec, loadQueue()) {
|
QListIterator<PluginSpec *> it(loadQueue());
|
||||||
spec->d->disableIndirectlyIfDependencyDisabled();
|
it.toBack();
|
||||||
|
while (it.hasPrevious()) {
|
||||||
|
PluginSpec *spec = it.previous();
|
||||||
|
spec->d->enableDependenciesIndirectly();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -124,6 +124,8 @@ public:
|
|||||||
static QList<PluginSpec *> plugins();
|
static QList<PluginSpec *> plugins();
|
||||||
static QHash<QString, PluginCollection *> pluginCollections();
|
static QHash<QString, PluginCollection *> pluginCollections();
|
||||||
static bool hasError();
|
static bool hasError();
|
||||||
|
static QSet<PluginSpec *> pluginsRequiringPlugin(PluginSpec *spec);
|
||||||
|
static QSet<PluginSpec *> pluginsRequiredByPlugin(PluginSpec *spec);
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
static void setSettings(QSettings *settings);
|
static void setSettings(QSettings *settings);
|
||||||
|
@@ -284,8 +284,9 @@ bool PluginSpec::isEnabledByDefault() const
|
|||||||
Returns whether the plugin should be loaded at startup,
|
Returns whether the plugin should be loaded at startup,
|
||||||
taking into account the default enabled state, and the user's settings.
|
taking into account the default enabled state, and the user's settings.
|
||||||
|
|
||||||
\note This function returns true even if a plugin is disabled because its
|
\note This function might return false even if the plugin is loaded as a requirement of another
|
||||||
dependencies were not loaded, or an error occurred during loading it.
|
enabled plugin.
|
||||||
|
\sa PluginSpec::isEffectivelyEnabled
|
||||||
*/
|
*/
|
||||||
bool PluginSpec::isEnabledBySettings() const
|
bool PluginSpec::isEnabledBySettings() const
|
||||||
{
|
{
|
||||||
@@ -294,24 +295,25 @@ bool PluginSpec::isEnabledBySettings() const
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns whether the plugin is loaded at startup.
|
Returns whether the plugin is loaded at startup.
|
||||||
\see PluginSpec::isEnabled
|
\see PluginSpec::isEnabledBySettings
|
||||||
*/
|
*/
|
||||||
bool PluginSpec::isEffectivelyEnabled() const
|
bool PluginSpec::isEffectivelyEnabled() const
|
||||||
{
|
{
|
||||||
if (d->disabledIndirectly
|
if (!isAvailableForHostPlatform())
|
||||||
|| (!d->enabledBySettings && !d->forceEnabled)
|
|
||||||
|| d->forceDisabled) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
if (isForceEnabled() || isEnabledIndirectly())
|
||||||
return isAvailableForHostPlatform();
|
return true;
|
||||||
|
if (isForceDisabled())
|
||||||
|
return false;
|
||||||
|
return isEnabledBySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Returns true if loading was not done due to user unselecting this plugin or its dependencies.
|
Returns true if loading was not done due to user unselecting this plugin or its dependencies.
|
||||||
*/
|
*/
|
||||||
bool PluginSpec::isDisabledIndirectly() const
|
bool PluginSpec::isEnabledIndirectly() const
|
||||||
{
|
{
|
||||||
return d->disabledIndirectly;
|
return d->enabledIndirectly;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -486,7 +488,7 @@ PluginSpecPrivate::PluginSpecPrivate(PluginSpec *spec)
|
|||||||
experimental(false),
|
experimental(false),
|
||||||
enabledByDefault(true),
|
enabledByDefault(true),
|
||||||
enabledBySettings(true),
|
enabledBySettings(true),
|
||||||
disabledIndirectly(false),
|
enabledIndirectly(false),
|
||||||
forceEnabled(false),
|
forceEnabled(false),
|
||||||
forceDisabled(false),
|
forceDisabled(false),
|
||||||
plugin(0),
|
plugin(0),
|
||||||
@@ -910,24 +912,18 @@ bool PluginSpecPrivate::resolveDependencies(const QList<PluginSpec *> &specs)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PluginSpecPrivate::disableIndirectlyIfDependencyDisabled()
|
void PluginSpecPrivate::enableDependenciesIndirectly()
|
||||||
{
|
{
|
||||||
if (!enabledBySettings)
|
if (!q->isEffectivelyEnabled()) // plugin not enabled, nothing to do
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (disabledIndirectly)
|
|
||||||
return;
|
|
||||||
|
|
||||||
QHashIterator<PluginDependency, PluginSpec *> it(dependencySpecs);
|
QHashIterator<PluginDependency, PluginSpec *> it(dependencySpecs);
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
it.next();
|
it.next();
|
||||||
if (it.key().type != PluginDependency::Required)
|
if (it.key().type != PluginDependency::Required)
|
||||||
continue;
|
continue;
|
||||||
PluginSpec *dependencySpec = it.value();
|
PluginSpec *dependencySpec = it.value();
|
||||||
if (!dependencySpec->isEffectivelyEnabled()) {
|
if (!dependencySpec->isEffectivelyEnabled())
|
||||||
disabledIndirectly = true;
|
dependencySpec->d->enabledIndirectly = true;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -53,7 +53,7 @@ class PluginManagerPrivate;
|
|||||||
} // Internal
|
} // Internal
|
||||||
|
|
||||||
class IPlugin;
|
class IPlugin;
|
||||||
class PluginItem;
|
class PluginView;
|
||||||
|
|
||||||
struct EXTENSIONSYSTEM_EXPORT PluginDependency
|
struct EXTENSIONSYSTEM_EXPORT PluginDependency
|
||||||
{
|
{
|
||||||
@@ -104,7 +104,7 @@ public:
|
|||||||
bool isEnabledByDefault() const;
|
bool isEnabledByDefault() const;
|
||||||
bool isEnabledBySettings() const;
|
bool isEnabledBySettings() const;
|
||||||
bool isEffectivelyEnabled() const;
|
bool isEffectivelyEnabled() const;
|
||||||
bool isDisabledIndirectly() const;
|
bool isEnabledIndirectly() const;
|
||||||
bool isForceEnabled() const;
|
bool isForceEnabled() const;
|
||||||
bool isForceDisabled() const;
|
bool isForceDisabled() const;
|
||||||
QVector<PluginDependency> dependencies() const;
|
QVector<PluginDependency> dependencies() const;
|
||||||
@@ -137,7 +137,7 @@ private:
|
|||||||
PluginSpec();
|
PluginSpec();
|
||||||
|
|
||||||
Internal::PluginSpecPrivate *d;
|
Internal::PluginSpecPrivate *d;
|
||||||
friend class PluginItem;
|
friend class PluginView;
|
||||||
friend class Internal::OptionsParser;
|
friend class Internal::OptionsParser;
|
||||||
friend class Internal::PluginManagerPrivate;
|
friend class Internal::PluginManagerPrivate;
|
||||||
friend class Internal::PluginSpecPrivate;
|
friend class Internal::PluginSpecPrivate;
|
||||||
|
@@ -88,7 +88,7 @@ public:
|
|||||||
QRegExp platformSpecification;
|
QRegExp platformSpecification;
|
||||||
QVector<PluginDependency> dependencies;
|
QVector<PluginDependency> dependencies;
|
||||||
bool enabledBySettings;
|
bool enabledBySettings;
|
||||||
bool disabledIndirectly;
|
bool enabledIndirectly;
|
||||||
bool forceEnabled;
|
bool forceEnabled;
|
||||||
bool forceDisabled;
|
bool forceDisabled;
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ public:
|
|||||||
static bool isValidVersion(const QString &version);
|
static bool isValidVersion(const QString &version);
|
||||||
static int versionCompare(const QString &version1, const QString &version2);
|
static int versionCompare(const QString &version1, const QString &version2);
|
||||||
|
|
||||||
void disableIndirectlyIfDependencyDisabled();
|
void enableDependenciesIndirectly();
|
||||||
|
|
||||||
bool readMetaData(const QJsonObject &metaData);
|
bool readMetaData(const QJsonObject &metaData);
|
||||||
|
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QItemSelectionModel>
|
#include <QItemSelectionModel>
|
||||||
|
#include <QMessageBox>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
@@ -107,8 +108,20 @@ public:
|
|||||||
case NameColumn:
|
case NameColumn:
|
||||||
if (role == Qt::DisplayRole)
|
if (role == Qt::DisplayRole)
|
||||||
return m_spec->name();
|
return m_spec->name();
|
||||||
if (role == Qt::ToolTipRole)
|
if (role == Qt::ToolTipRole) {
|
||||||
return QDir::toNativeSeparators(m_spec->filePath());
|
QString toolTip;
|
||||||
|
if (!m_spec->isAvailableForHostPlatform())
|
||||||
|
toolTip = PluginView::tr("Path: %1\nPlugin is not available on this platform.");
|
||||||
|
else if (m_spec->isEnabledIndirectly())
|
||||||
|
toolTip = PluginView::tr("Path: %1\nPlugin is enabled as dependency of an enabled plugin.");
|
||||||
|
else if (m_spec->isForceEnabled())
|
||||||
|
toolTip = PluginView::tr("Path: %1\nPlugin is enabled by command line argument.");
|
||||||
|
else if (m_spec->isForceDisabled())
|
||||||
|
toolTip = PluginView::tr("Path: %1\nPlugin is disabled by command line argument.");
|
||||||
|
else
|
||||||
|
toolTip = PluginView::tr("Path: %1");
|
||||||
|
return toolTip.arg(QDir::toNativeSeparators(m_spec->filePath()));
|
||||||
|
}
|
||||||
if (role == Qt::DecorationRole) {
|
if (role == Qt::DecorationRole) {
|
||||||
bool ok = !m_spec->hasError();
|
bool ok = !m_spec->hasError();
|
||||||
QIcon i = icon(ok ? OkIcon : ErrorIcon);
|
QIcon i = icon(ok ? OkIcon : ErrorIcon);
|
||||||
@@ -153,24 +166,14 @@ public:
|
|||||||
|
|
||||||
bool setData(int column, const QVariant &data, int role)
|
bool setData(int column, const QVariant &data, int role)
|
||||||
{
|
{
|
||||||
if (column == LoadedColumn && role == Qt::CheckStateRole) {
|
if (column == LoadedColumn && role == Qt::CheckStateRole)
|
||||||
m_spec->d->setEnabledBySettings(data.toBool());
|
return m_view->setPluginsEnabled(QSet<PluginSpec *>() << m_spec, data.toBool());
|
||||||
updateColumn(column);
|
|
||||||
parent()->updateColumn(column);
|
|
||||||
emit m_view->pluginSettingsChanged(m_spec);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isEnabled() const
|
bool isEnabled() const
|
||||||
{
|
{
|
||||||
if (m_spec->isRequired() || !m_spec->isAvailableForHostPlatform())
|
return m_spec->isAvailableForHostPlatform() && !m_spec->isRequired();
|
||||||
return false;
|
|
||||||
foreach (PluginSpec *spec, m_view->m_pluginDependencies.value(m_spec))
|
|
||||||
if (!spec->isEnabledBySettings())
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::ItemFlags flags(int column) const
|
Qt::ItemFlags flags(int column) const
|
||||||
@@ -245,10 +248,13 @@ public:
|
|||||||
bool setData(int column, const QVariant &data, int role)
|
bool setData(int column, const QVariant &data, int role)
|
||||||
{
|
{
|
||||||
if (column == LoadedColumn && role == Qt::CheckStateRole) {
|
if (column == LoadedColumn && role == Qt::CheckStateRole) {
|
||||||
|
QSet<PluginSpec *> affectedPlugins;
|
||||||
foreach (TreeItem *item, children())
|
foreach (TreeItem *item, children())
|
||||||
static_cast<PluginItem *>(item)->setData(column, data, role);
|
affectedPlugins.insert(static_cast<PluginItem *>(item)->m_spec);
|
||||||
update();
|
if (m_view->setPluginsEnabled(affectedPlugins, data.toBool())) {
|
||||||
return true;
|
update();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -336,29 +342,8 @@ PluginSpec *PluginView::pluginForIndex(const QModelIndex &index) const
|
|||||||
return item ? item->m_spec: 0;
|
return item ? item->m_spec: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void queryDependendPlugins(PluginSpec *spec, QSet<PluginSpec *> *dependencies)
|
|
||||||
{
|
|
||||||
QHashIterator<PluginDependency, PluginSpec *> it(spec->dependencySpecs());
|
|
||||||
while (it.hasNext()) {
|
|
||||||
it.next();
|
|
||||||
PluginSpec *dep = it.value();
|
|
||||||
if (!dependencies->contains(dep)) {
|
|
||||||
dependencies->insert(dep);
|
|
||||||
queryDependendPlugins(dep, dependencies);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PluginView::updatePlugins()
|
void PluginView::updatePlugins()
|
||||||
{
|
{
|
||||||
// Dependencies.
|
|
||||||
m_pluginDependencies.clear();
|
|
||||||
foreach (PluginSpec *spec, PluginManager::loadQueue()) {
|
|
||||||
QSet<PluginSpec *> deps;
|
|
||||||
queryDependendPlugins(spec, &deps);
|
|
||||||
m_pluginDependencies[spec] = deps;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Model.
|
// Model.
|
||||||
m_model->removeItems();
|
m_model->removeItems();
|
||||||
|
|
||||||
@@ -392,4 +377,64 @@ void PluginView::updatePlugins()
|
|||||||
m_categoryView->expandAll();
|
m_categoryView->expandAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString pluginListString(const QSet<PluginSpec *> &plugins)
|
||||||
|
{
|
||||||
|
QStringList names = Utils::transform<QList>(plugins, &PluginSpec::name);
|
||||||
|
names.sort();
|
||||||
|
return names.join(QLatin1Char('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PluginView::setPluginsEnabled(const QSet<PluginSpec *> &plugins, bool enable)
|
||||||
|
{
|
||||||
|
QSet<PluginSpec *> additionalPlugins;
|
||||||
|
if (enable) {
|
||||||
|
foreach (PluginSpec *spec, plugins) {
|
||||||
|
foreach (PluginSpec *other, PluginManager::pluginsRequiredByPlugin(spec)) {
|
||||||
|
if (!other->isEnabledBySettings())
|
||||||
|
additionalPlugins.insert(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
additionalPlugins.subtract(plugins);
|
||||||
|
if (!additionalPlugins.isEmpty()) {
|
||||||
|
if (QMessageBox::question(this, tr("Enabling Plugins"),
|
||||||
|
tr("Enabling\n%1\nwill also enable the following plugins:\n\n%2")
|
||||||
|
.arg(pluginListString(plugins))
|
||||||
|
.arg(pluginListString(additionalPlugins)),
|
||||||
|
QMessageBox::Ok | QMessageBox::Cancel,
|
||||||
|
QMessageBox::Ok) != QMessageBox::Ok)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach (PluginSpec *spec, plugins) {
|
||||||
|
foreach (PluginSpec *other, PluginManager::pluginsRequiringPlugin(spec)) {
|
||||||
|
if (other->isEnabledBySettings())
|
||||||
|
additionalPlugins.insert(other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
additionalPlugins.subtract(plugins);
|
||||||
|
if (!additionalPlugins.isEmpty()) {
|
||||||
|
if (QMessageBox::question(this, tr("Disabling Plugins"),
|
||||||
|
tr("Disabling\n%1\nwill also disable the following plugins:\n\n%2")
|
||||||
|
.arg(pluginListString(plugins))
|
||||||
|
.arg(pluginListString(additionalPlugins)),
|
||||||
|
QMessageBox::Ok | QMessageBox::Cancel,
|
||||||
|
QMessageBox::Ok) != QMessageBox::Ok)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<PluginSpec *> affectedPlugins = plugins + additionalPlugins;
|
||||||
|
foreach (PluginSpec *spec, affectedPlugins) {
|
||||||
|
PluginItem *item = m_model->findItemAtLevel<PluginItem *>(2, [spec](PluginItem *item) {
|
||||||
|
return item->m_spec == spec;
|
||||||
|
});
|
||||||
|
QTC_ASSERT(item, continue);
|
||||||
|
spec->d->setEnabledBySettings(enable);
|
||||||
|
item->updateColumn(LoadedColumn);
|
||||||
|
item->parent()->updateColumn(LoadedColumn);
|
||||||
|
emit pluginSettingsChanged(spec);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ExtensionSystem
|
} // namespace ExtensionSystem
|
||||||
|
@@ -72,6 +72,7 @@ signals:
|
|||||||
private:
|
private:
|
||||||
PluginSpec *pluginForIndex(const QModelIndex &index) const;
|
PluginSpec *pluginForIndex(const QModelIndex &index) const;
|
||||||
void updatePlugins();
|
void updatePlugins();
|
||||||
|
bool setPluginsEnabled(const QSet<PluginSpec *> &plugins, bool enable);
|
||||||
|
|
||||||
Utils::TreeView *m_categoryView;
|
Utils::TreeView *m_categoryView;
|
||||||
Utils::TreeModel *m_model;
|
Utils::TreeModel *m_model;
|
||||||
@@ -79,7 +80,6 @@ private:
|
|||||||
|
|
||||||
friend class CollectionItem;
|
friend class CollectionItem;
|
||||||
friend class PluginItem;
|
friend class PluginItem;
|
||||||
QHash<PluginSpec *, QSet<PluginSpec *>> m_pluginDependencies;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespae ExtensionSystem
|
} // namespae ExtensionSystem
|
||||||
|
Reference in New Issue
Block a user