forked from qt-creator/qt-creator
Plugin manager for enabling/disabling plugins
Go to About Plugins and enable/disable plugins from there. Reviewed-by: mae
This commit is contained in:
@@ -31,11 +31,14 @@
|
||||
#include "pluginview_p.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "pluginspec.h"
|
||||
#include "plugincollection.h"
|
||||
#include "ui_pluginview.h"
|
||||
|
||||
#include <QtCore/QDir>
|
||||
#include <QtGui/QHeaderView>
|
||||
#include <QtGui/QTreeWidgetItem>
|
||||
#include <QtGui/QPalette>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
/*!
|
||||
@@ -65,6 +68,7 @@
|
||||
using namespace ExtensionSystem;
|
||||
|
||||
Q_DECLARE_METATYPE(ExtensionSystem::PluginSpec*);
|
||||
Q_DECLARE_METATYPE(ExtensionSystem::PluginCollection*);
|
||||
|
||||
/*!
|
||||
\fn PluginView::PluginView(PluginManager *manager, QWidget *parent)
|
||||
@@ -74,20 +78,30 @@ Q_DECLARE_METATYPE(ExtensionSystem::PluginSpec*);
|
||||
PluginView::PluginView(PluginManager *manager, QWidget *parent)
|
||||
: QWidget(parent),
|
||||
m_ui(new Internal::Ui::PluginView),
|
||||
p(new Internal::PluginViewPrivate)
|
||||
p(new Internal::PluginViewPrivate),
|
||||
m_allowCheckStateUpdate(true),
|
||||
C_LOAD(1)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
QHeaderView *header = m_ui->pluginWidget->header();
|
||||
QHeaderView *header = m_ui->categoryWidget->header();
|
||||
header->setResizeMode(0, QHeaderView::ResizeToContents);
|
||||
header->setResizeMode(1, QHeaderView::ResizeToContents);
|
||||
header->setResizeMode(2, QHeaderView::ResizeToContents);
|
||||
m_ui->pluginWidget->sortItems(1, Qt::AscendingOrder);
|
||||
|
||||
m_okIcon = QIcon(QLatin1String(":/extensionsystem/images/ok.png"));
|
||||
m_errorIcon = QIcon(QLatin1String(":/extensionsystem/images/error.png"));
|
||||
m_notLoadedIcon = QIcon(QLatin1String(":/extensionsystem/images/notloaded.png"));
|
||||
|
||||
// cannot disable these
|
||||
m_whitelist << QString("Core") << QString("Locator")
|
||||
<< QString("Find") << QString("TextEditor");
|
||||
|
||||
p->manager = manager;
|
||||
connect(p->manager, SIGNAL(pluginsChanged()), this, SLOT(updateList()));
|
||||
connect(m_ui->pluginWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
|
||||
connect(m_ui->categoryWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
|
||||
this, SLOT(selectPlugin(QTreeWidgetItem*)));
|
||||
connect(m_ui->pluginWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)),
|
||||
connect(m_ui->categoryWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)),
|
||||
this, SLOT(activatePlugin(QTreeWidgetItem*)));
|
||||
|
||||
updateList();
|
||||
}
|
||||
|
||||
@@ -107,51 +121,230 @@ PluginView::~PluginView()
|
||||
*/
|
||||
PluginSpec *PluginView::currentPlugin() const
|
||||
{
|
||||
if (!m_ui->pluginWidget->currentItem())
|
||||
if (!m_ui->categoryWidget->currentItem())
|
||||
return 0;
|
||||
return m_ui->pluginWidget->currentItem()->data(0, Qt::UserRole).value<PluginSpec *>();
|
||||
if (!m_ui->categoryWidget->currentItem()->data(0, Qt::UserRole).isNull())
|
||||
return m_ui->categoryWidget->currentItem()->data(0, Qt::UserRole).value<PluginSpec *>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PluginView::updateList()
|
||||
{
|
||||
const QIcon okIcon(QLatin1String(":/extensionsystem/images/ok.png"));
|
||||
const QIcon errorIcon(QLatin1String(":/extensionsystem/images/error.png"));
|
||||
QList<QTreeWidgetItem *> items;
|
||||
QTreeWidgetItem *currentItem = 0;
|
||||
PluginSpec *currPlugin = currentPlugin();
|
||||
foreach (PluginSpec *spec, p->manager->plugins()) {
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(QStringList()
|
||||
<< QString()
|
||||
<< spec->name()
|
||||
<< QString::fromLatin1("%1 (%2)").arg(spec->version(), spec->compatVersion())
|
||||
<< spec->vendor()
|
||||
<< QDir::toNativeSeparators(spec->filePath()));
|
||||
item->setToolTip(4, QDir::toNativeSeparators(spec->filePath()));
|
||||
item->setIcon(0, spec->hasError() ? errorIcon : okIcon);
|
||||
item->setData(0, Qt::UserRole, qVariantFromValue(spec));
|
||||
items.append(item);
|
||||
if (currPlugin == spec)
|
||||
currentItem = item;
|
||||
connect(m_ui->categoryWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
|
||||
this, SLOT(updatePluginSettings(QTreeWidgetItem*, int)));
|
||||
|
||||
PluginCollection *defaultCollection = 0;
|
||||
foreach(PluginCollection *collection, p->manager->pluginCollections()) {
|
||||
if (collection->name().isEmpty()) {
|
||||
defaultCollection = collection;
|
||||
continue;
|
||||
}
|
||||
// State, name, load, version, vendor.
|
||||
QTreeWidgetItem *collectionItem = new QTreeWidgetItem(QStringList()
|
||||
<< collection->name()
|
||||
<< QString() // state
|
||||
<< QString() // load
|
||||
<< QString() // version
|
||||
<< QString()); // vendor
|
||||
m_items.append(collectionItem);
|
||||
|
||||
Qt::CheckState groupState = Qt::Unchecked;
|
||||
bool hasErrors = parsePluginSpecs(collectionItem, groupState, collection->plugins());
|
||||
|
||||
collectionItem->setIcon(0, hasErrors ? m_errorIcon : m_okIcon);
|
||||
collectionItem->setData(C_LOAD, Qt::CheckStateRole, QVariant(groupState));
|
||||
collectionItem->setToolTip(C_LOAD, tr("Load on Startup"));
|
||||
collectionItem->setData(0, Qt::UserRole, qVariantFromValue(collection));
|
||||
}
|
||||
m_ui->pluginWidget->clear();
|
||||
if (!items.isEmpty())
|
||||
m_ui->pluginWidget->addTopLevelItems(items);
|
||||
if (currentItem)
|
||||
m_ui->pluginWidget->setCurrentItem(currentItem);
|
||||
else if (!items.isEmpty())
|
||||
m_ui->pluginWidget->setCurrentItem(items.first());
|
||||
|
||||
// add all non-categorized plugins into utilities. could also be added as root items
|
||||
// but that makes the tree ugly.
|
||||
QTreeWidgetItem *defaultCollectionItem = new QTreeWidgetItem(QStringList()
|
||||
<< QString(tr("Utilities"))
|
||||
<< QString()
|
||||
<< QString()
|
||||
<< QString()
|
||||
<< QString());
|
||||
|
||||
m_items.append(defaultCollectionItem);
|
||||
Qt::CheckState groupState = Qt::Unchecked;
|
||||
bool hasErrors = parsePluginSpecs(defaultCollectionItem, groupState, defaultCollection->plugins());
|
||||
|
||||
defaultCollectionItem->setIcon(0, hasErrors ? m_errorIcon : m_okIcon);
|
||||
defaultCollectionItem->setData(C_LOAD, Qt::CheckStateRole, QVariant(groupState));
|
||||
defaultCollectionItem->setToolTip(C_LOAD, tr("Load on Startup"));
|
||||
defaultCollectionItem->setData(0, Qt::UserRole, qVariantFromValue(defaultCollection));
|
||||
|
||||
|
||||
foreach (PluginSpec *spec, m_specToItem.keys())
|
||||
toggleRelatedPlugins(spec, spec->loadOnStartup() && !spec->ignoreOnStartup());
|
||||
|
||||
m_ui->categoryWidget->clear();
|
||||
if (!m_items.isEmpty()) {
|
||||
m_ui->categoryWidget->addTopLevelItems(m_items);
|
||||
m_ui->categoryWidget->expandAll();
|
||||
}
|
||||
|
||||
m_ui->categoryWidget->sortItems(0, Qt::AscendingOrder);
|
||||
if (m_ui->categoryWidget->topLevelItemCount())
|
||||
m_ui->categoryWidget->setCurrentItem(m_ui->categoryWidget->topLevelItem(0));
|
||||
}
|
||||
|
||||
bool PluginView::parsePluginSpecs(QTreeWidgetItem *parentItem, Qt::CheckState &groupState, QList<PluginSpec*> plugins)
|
||||
{
|
||||
bool hasErrors = false;
|
||||
int loadCount = 0;
|
||||
for (int i = 0; i < plugins.length(); ++i) {
|
||||
PluginSpec *spec = plugins[i];
|
||||
if (spec->hasError())
|
||||
hasErrors = true;
|
||||
|
||||
QTreeWidgetItem *pluginItem = new QTreeWidgetItem(QStringList()
|
||||
<< spec->name()
|
||||
<< QString() // load on startup
|
||||
<< QString::fromLatin1("%1 (%2)").arg(spec->version(), spec->compatVersion())
|
||||
<< spec->vendor());
|
||||
|
||||
pluginItem->setToolTip(0, QDir::toNativeSeparators(spec->filePath()));
|
||||
bool ok = !spec->hasError();
|
||||
QIcon &icon = ok ? m_okIcon : m_errorIcon;
|
||||
if (ok && (spec->state() != PluginSpec::Running))
|
||||
icon = m_notLoadedIcon;
|
||||
|
||||
pluginItem->setIcon(0, icon);
|
||||
pluginItem->setData(0, Qt::UserRole, qVariantFromValue(spec));
|
||||
|
||||
Qt::CheckState state = Qt::Unchecked;
|
||||
if (spec->loadOnStartup()) {
|
||||
state = Qt::Checked;
|
||||
//if (!spec->ignoreOnStartup())
|
||||
++loadCount;
|
||||
} else
|
||||
hasErrors = true;
|
||||
|
||||
if (!m_whitelist.contains(spec->name()))
|
||||
pluginItem->setData(C_LOAD, Qt::CheckStateRole, state);
|
||||
else {
|
||||
QColor disabledColor = palette().color(QPalette::Disabled,QPalette::WindowText).lighter(120);
|
||||
pluginItem->setData(C_LOAD, Qt::CheckStateRole, Qt::Checked);
|
||||
pluginItem->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
pluginItem->setSizeHint(C_LOAD, QSize(1,1));
|
||||
pluginItem->setForeground(C_LOAD, QBrush(disabledColor)); // QBrush(Qt::white, Qt::NoBrush));
|
||||
//pluginItem->setBackground(C_LOAD, QBrush(Qt::white, Qt::NoBrush));
|
||||
}
|
||||
pluginItem->setToolTip(C_LOAD, tr("Load on Startup"));
|
||||
|
||||
m_specToItem.insert(spec, pluginItem);
|
||||
|
||||
if (parentItem)
|
||||
parentItem->addChild(pluginItem);
|
||||
else
|
||||
m_items.append(pluginItem);
|
||||
|
||||
}
|
||||
|
||||
if (loadCount == plugins.length())
|
||||
groupState = Qt::Checked;
|
||||
else if (loadCount == 0)
|
||||
groupState = Qt::Unchecked;
|
||||
else
|
||||
groupState = Qt::PartiallyChecked;
|
||||
|
||||
return hasErrors;
|
||||
}
|
||||
|
||||
void PluginView::selectPlugin(QTreeWidgetItem *current)
|
||||
{
|
||||
if (!current)
|
||||
emit currentPluginChanged(0);
|
||||
else
|
||||
else if (current->data(0, Qt::UserRole).canConvert<PluginSpec*>())
|
||||
emit currentPluginChanged(current->data(0, Qt::UserRole).value<PluginSpec *>());
|
||||
else
|
||||
emit currentPluginChanged(0);
|
||||
|
||||
}
|
||||
|
||||
void PluginView::activatePlugin(QTreeWidgetItem *item)
|
||||
{
|
||||
emit pluginActivated(item->data(0, Qt::UserRole).value<PluginSpec *>());
|
||||
if (item->data(0, Qt::UserRole).canConvert<PluginSpec*>()) {
|
||||
emit pluginActivated(item->data(0, Qt::UserRole).value<PluginSpec *>());
|
||||
} else
|
||||
emit pluginActivated(0);
|
||||
}
|
||||
|
||||
void PluginView::updatePluginSettings(QTreeWidgetItem *item, int column)
|
||||
{
|
||||
if (!m_allowCheckStateUpdate)
|
||||
return;
|
||||
|
||||
m_allowCheckStateUpdate = false;
|
||||
|
||||
bool loadOnStartup = item->data(C_LOAD, Qt::CheckStateRole).toBool();
|
||||
|
||||
if (item->data(0, Qt::UserRole).canConvert<PluginSpec*>()) {
|
||||
PluginSpec *spec = item->data(0, Qt::UserRole).value<PluginSpec *>();
|
||||
|
||||
if (column == C_LOAD) {
|
||||
|
||||
spec->setLoadOnStartup(loadOnStartup);
|
||||
toggleRelatedPlugins(spec, loadOnStartup);
|
||||
|
||||
if (item->parent()) {
|
||||
PluginCollection *collection = item->parent()->data(0, Qt::UserRole).value<PluginCollection *>();
|
||||
Qt::CheckState state = Qt::PartiallyChecked;
|
||||
int loadCount = 0;
|
||||
for (int i = 0; i < collection->plugins().length(); ++i) {
|
||||
if (collection->plugins().at(i)->loadOnStartup())
|
||||
++loadCount;
|
||||
}
|
||||
if (loadCount == collection->plugins().length())
|
||||
state = Qt::Checked;
|
||||
else if (loadCount == 0)
|
||||
state = Qt::Unchecked;
|
||||
|
||||
item->parent()->setData(C_LOAD, Qt::CheckStateRole, state);
|
||||
}
|
||||
|
||||
emit pluginSettingsChanged(spec);
|
||||
}
|
||||
|
||||
} else {
|
||||
PluginCollection *collection = item->data(0, Qt::UserRole).value<PluginCollection *>();
|
||||
for (int i = 0; i < collection->plugins().length(); ++i) {
|
||||
PluginSpec *spec = collection->plugins().at(i);
|
||||
QTreeWidgetItem *child = m_specToItem.value(spec);
|
||||
|
||||
if (!m_whitelist.contains(spec->name())) {
|
||||
spec->setLoadOnStartup(loadOnStartup);
|
||||
Qt::CheckState state = (loadOnStartup ? Qt::Checked : Qt::Unchecked);
|
||||
child->setData(C_LOAD, Qt::CheckStateRole, state);
|
||||
toggleRelatedPlugins(spec, loadOnStartup);
|
||||
} else {
|
||||
child->setData(C_LOAD, Qt::CheckStateRole, Qt::Checked);
|
||||
child->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
}
|
||||
}
|
||||
emit pluginSettingsChanged(collection->plugins().first());
|
||||
}
|
||||
|
||||
m_allowCheckStateUpdate = true;
|
||||
}
|
||||
|
||||
void PluginView::toggleRelatedPlugins(PluginSpec *modifiedPlugin, bool isPluginEnabled)
|
||||
{
|
||||
|
||||
for(int i = 0; i < modifiedPlugin->providesSpecs().length(); ++i) {
|
||||
PluginSpec *spec = modifiedPlugin->providesSpecs().at(i);
|
||||
QTreeWidgetItem *childItem = m_specToItem.value(spec);
|
||||
|
||||
if (childItem->isDisabled() != !isPluginEnabled) {
|
||||
childItem->setDisabled(!isPluginEnabled);
|
||||
if (childItem->parent() && !childItem->parent()->isExpanded())
|
||||
childItem->parent()->setExpanded(true);
|
||||
|
||||
|
||||
toggleRelatedPlugins(spec, isPluginEnabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user