diff --git a/doc/api/plugin-metadata.qdoc b/doc/api/plugin-metadata.qdoc index 83641974d7e..bb772f056cf 100644 --- a/doc/api/plugin-metadata.qdoc +++ b/doc/api/plugin-metadata.qdoc @@ -81,6 +81,13 @@ If set, the respective plugin is not loaded by default but must be explicitly enabled by the user. This should be done for plugins which are not expected to be used by so many people as to justify the additional resource consumption. + \row + \li HiddenByDefault + \li Boolean + \li Optional. Defaults to \c false. + If set, the plugin is not shown in the default view in the + \uicontrol {About Plugins...} dialog, but only if the user requests seeing all + plugins. It is still shown with the \c{-version} command line option. \row \li Required \li Boolean diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp index 61e2fb0451c..c839b8ea3fe 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -277,6 +277,11 @@ bool PluginSpec::isRequired() const return d->required; } +bool PluginSpec::isHiddenByDefault() const +{ + return d->hiddenByDefault; +} + /*! Returns whether the plugin has its experimental flag set. */ @@ -482,6 +487,7 @@ namespace { const char PLUGIN_VERSION[] = "Version"; const char PLUGIN_COMPATVERSION[] = "CompatVersion"; const char PLUGIN_REQUIRED[] = "Required"; + const char PLUGIN_HIDDEN_BY_DEFAULT[] = "HiddenByDefault"; const char PLUGIN_EXPERIMENTAL[] = "Experimental"; const char PLUGIN_DISABLED_BY_DEFAULT[] = "DisabledByDefault"; const char VENDOR[] = "Vendor"; @@ -692,6 +698,12 @@ bool PluginSpecPrivate::readMetaData(const QJsonObject &metaData) required = value.toBool(false); qCDebug(pluginLog) << "required =" << required; + value = pluginInfo.value(QLatin1String(PLUGIN_HIDDEN_BY_DEFAULT)); + if (!value.isUndefined() && !value.isBool()) + return reportError(msgValueIsNotABool(PLUGIN_HIDDEN_BY_DEFAULT)); + hiddenByDefault = value.toBool(false); + qCDebug(pluginLog) << "hiddenByDefault =" << hiddenByDefault; + value = pluginInfo.value(QLatin1String(PLUGIN_EXPERIMENTAL)); if (!value.isUndefined() && !value.isBool()) return reportError(msgValueIsNotABool(PLUGIN_EXPERIMENTAL)); diff --git a/src/libs/extensionsystem/pluginspec.h b/src/libs/extensionsystem/pluginspec.h index 68c6fdd3154..64725c8e9f7 100644 --- a/src/libs/extensionsystem/pluginspec.h +++ b/src/libs/extensionsystem/pluginspec.h @@ -95,6 +95,7 @@ public: QRegExp platformSpecification() const; bool isAvailableForHostPlatform() const; bool isRequired() const; + bool isHiddenByDefault() const; bool isExperimental() const; bool isEnabledByDefault() const; bool isEnabledBySettings() const; diff --git a/src/libs/extensionsystem/pluginspec_p.h b/src/libs/extensionsystem/pluginspec_p.h index f4685e5e2ae..86790da8eca 100644 --- a/src/libs/extensionsystem/pluginspec_p.h +++ b/src/libs/extensionsystem/pluginspec_p.h @@ -71,6 +71,7 @@ public: QString version; QString compatVersion; bool required = false; + bool hiddenByDefault = false; bool experimental = false; bool enabledByDefault = true; QString vendor; diff --git a/src/libs/extensionsystem/pluginview.cpp b/src/libs/extensionsystem/pluginview.cpp index 4ce87cd6022..042e666c6aa 100644 --- a/src/libs/extensionsystem/pluginview.cpp +++ b/src/libs/extensionsystem/pluginview.cpp @@ -82,6 +82,7 @@ enum Columns { NameColumn, LoadedColumn, VersionColumn, VendorColumn, }; enum IconIndex { OkIcon, ErrorIcon, NotLoadedIcon }; static const int SortRole = Qt::UserRole + 1; +static const int HiddenByDefaultRole = Qt::UserRole + 2; static const QIcon &icon(IconIndex icon) { @@ -114,6 +115,8 @@ public: QVariant data(int column, int role) const { + if (role == HiddenByDefaultRole) + return m_spec->isHiddenByDefault() || !m_spec->isAvailableForHostPlatform(); switch (column) { case NameColumn: if (role == Qt::DisplayRole) @@ -223,6 +226,8 @@ public: QVariant data(int column, int role) const { + if (role == HiddenByDefaultRole) + return false; if (column == NameColumn) { if (role == Qt::DisplayRole || role == SortRole) return m_name; @@ -285,6 +290,40 @@ public: PluginView *m_view; // Not owned. }; +class PluginFilterModel : public CategorySortFilterModel +{ +public: + PluginFilterModel(QObject *parent = 0) : CategorySortFilterModel(parent) {} + + void setShowHidden(bool show) + { + if (show == m_showHidden) + return; + m_showHidden = show; + invalidateFilter(); + } + + bool isShowingHidden() const + { + return m_showHidden; + } + +protected: + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override + { + if (CategorySortFilterModel::filterAcceptsRow(source_row, source_parent)) { + if (m_showHidden) + return true; + const QModelIndex &index = sourceModel()->index(source_row, 0, source_parent); + return !sourceModel()->data(index, HiddenByDefaultRole).toBool(); + } + return false; + } + +private: + bool m_showHidden = true; +}; + } // Internal using namespace ExtensionSystem::Internal; @@ -312,7 +351,7 @@ PluginView::PluginView(QWidget *parent) m_model = new TreeModel(this); m_model->setHeader({ tr("Name"), tr("Load"), tr("Version"), tr("Vendor") }); - m_sortModel = new CategorySortFilterModel(this); + m_sortModel = new PluginFilterModel(this); m_sortModel->setSourceModel(m_model); m_sortModel->setSortRole(SortRole); m_sortModel->setFilterCaseSensitivity(Qt::CaseInsensitive); @@ -360,6 +399,17 @@ void PluginView::setFilter(const QString &filter) m_categoryView->expandAll(); } +void PluginView::setShowHidden(bool showHidden) +{ + m_sortModel->setShowHidden(showHidden); + m_categoryView->expandAll(); +} + +bool PluginView::isShowingHidden() const +{ + return m_sortModel->isShowingHidden(); +} + PluginSpec *PluginView::pluginForIndex(const QModelIndex &index) const { const QModelIndex &sourceIndex = m_sortModel->mapToSource(index); diff --git a/src/libs/extensionsystem/pluginview.h b/src/libs/extensionsystem/pluginview.h index 50fe7482e03..44ca2e2b129 100644 --- a/src/libs/extensionsystem/pluginview.h +++ b/src/libs/extensionsystem/pluginview.h @@ -45,8 +45,9 @@ class PluginManager; class PluginSpec; namespace Internal { -class PluginItem; class CollectionItem; +class PluginFilterModel; +class PluginItem; } // Internal class EXTENSIONSYSTEM_EXPORT PluginView : public QWidget @@ -59,6 +60,8 @@ public: PluginSpec *currentPlugin() const; void setFilter(const QString &filter); + void setShowHidden(bool showHidden); + bool isShowingHidden() const; signals: void currentPluginChanged(ExtensionSystem::PluginSpec *spec); @@ -72,7 +75,7 @@ private: Utils::TreeView *m_categoryView; Utils::TreeModel *m_model; - QSortFilterProxyModel *m_sortModel; + Internal::PluginFilterModel *m_sortModel; friend class Internal::CollectionItem; friend class Internal::PluginItem; diff --git a/src/libs/utils/categorysortfiltermodel.cpp b/src/libs/utils/categorysortfiltermodel.cpp index 4e83deba0ee..ab1769f8bd1 100644 --- a/src/libs/utils/categorysortfiltermodel.cpp +++ b/src/libs/utils/categorysortfiltermodel.cpp @@ -42,14 +42,9 @@ bool CategorySortFilterModel::filterAcceptsRow(int source_row, if (regexp.indexIn(sourceModel()->data(categoryIndex, filterRole()).toString()) != -1) return true; const int rowCount = sourceModel()->rowCount(categoryIndex); - const int columnCount = sourceModel()->columnCount(categoryIndex); for (int row = 0; row < rowCount; ++row) { - for (int column = 0; column < columnCount; ++column) { - if (regexp.indexIn(sourceModel()->data( - sourceModel()->index(row, column, categoryIndex), - filterRole()).toString()) != -1) - return true; - } + if (filterAcceptsRow(row, categoryIndex)) + return true; } return false; } diff --git a/src/plugins/coreplugin/plugindialog.cpp b/src/plugins/coreplugin/plugindialog.cpp index ac5677022f1..27436952fbd 100644 --- a/src/plugins/coreplugin/plugindialog.cpp +++ b/src/plugins/coreplugin/plugindialog.cpp @@ -35,6 +35,7 @@ #include #include +#include #include #include #include @@ -52,11 +53,21 @@ PluginDialog::PluginDialog(QWidget *parent) { QVBoxLayout *vl = new QVBoxLayout(this); + auto filterLayout = new QHBoxLayout; + vl->addLayout(filterLayout); auto filterEdit = new Utils::FancyLineEdit(this); filterEdit->setFiltering(true); connect(filterEdit, &Utils::FancyLineEdit::filterChanged, m_view, &ExtensionSystem::PluginView::setFilter); - vl->addWidget(filterEdit); + filterLayout->addWidget(filterEdit); + m_view->setShowHidden(false); + auto showHidden = new QCheckBox(tr("Show All")); + showHidden->setToolTip(tr("Show all installed plugins, including base plugins " + "and plugins that are not available on this platform.")); + showHidden->setChecked(m_view->isShowingHidden()); + connect(showHidden, &QCheckBox::stateChanged, + m_view, &ExtensionSystem::PluginView::setShowHidden); + filterLayout->addWidget(showHidden); vl->addWidget(m_view);