diff options
author | Lasse Holmstedt <[email protected]> | 2010-03-12 16:02:23 +0100 |
---|---|---|
committer | Lasse Holmstedt <[email protected]> | 2010-03-12 16:02:42 +0100 |
commit | 68c49a65e903c0b0cdda3322c843338cdf6f9900 (patch) | |
tree | 5a02ee898c8f6004ee6f05de22c8e77b3c62c011 /src/libs/extensionsystem/pluginview.cpp | |
parent | f4487c4c6728ec315f133479c07ab04332bdeffc (diff) |
Plugin manager for enabling/disabling plugins
Go to About Plugins and enable/disable plugins from there.
Reviewed-by: mae
Diffstat (limited to 'src/libs/extensionsystem/pluginview.cpp')
-rw-r--r-- | src/libs/extensionsystem/pluginview.cpp | 259 |
1 files changed, 226 insertions, 33 deletions
diff --git a/src/libs/extensionsystem/pluginview.cpp b/src/libs/extensionsystem/pluginview.cpp index c1c36de9364..286e12f7875 100644 --- a/src/libs/extensionsystem/pluginview.cpp +++ b/src/libs/extensionsystem/pluginview.cpp @@ -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() + 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)); + } + + // 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() - << 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; + << 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); + } - 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()); + + 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); + } + } } |