2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** Copyright (C) 2015 The Qt Company Ltd.
|
|
|
|
|
** Contact: http://www.qt.io/licensing
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2008-12-02 12:01:29 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2015-01-14 18:07:15 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms and
|
|
|
|
|
** conditions see http://www.qt.io/terms-conditions. For further information
|
2014-10-01 13:21:18 +02:00
|
|
|
** use the contact form at http://www.qt.io/contact-us.
|
2008-12-02 14:17:16 +01:00
|
|
|
**
|
2009-02-25 09:15:00 +01:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-10-02 09:12:39 +02:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2014-10-01 13:21:18 +02:00
|
|
|
** General Public License version 2.1 or version 3 as published by the Free
|
|
|
|
|
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
|
|
|
|
|
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
|
|
|
|
|
** following information to ensure the GNU Lesser General Public License
|
|
|
|
|
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
|
|
|
|
|
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
2012-10-02 09:12:39 +02:00
|
|
|
**
|
2015-01-14 18:07:15 +01:00
|
|
|
** In addition, as a special exception, The Qt Company gives you certain additional
|
|
|
|
|
** rights. These rights are described in The Qt Company LGPL Exception
|
2010-12-17 16:01:08 +01:00
|
|
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2008-12-02 14:09:21 +01:00
|
|
|
|
2008-12-02 12:01:29 +01:00
|
|
|
#include "pluginview.h"
|
|
|
|
|
#include "pluginmanager.h"
|
|
|
|
|
#include "pluginspec.h"
|
2010-03-12 16:02:23 +01:00
|
|
|
#include "plugincollection.h"
|
2015-01-13 09:08:41 +01:00
|
|
|
|
|
|
|
|
#include <utils/algorithm.h>
|
2014-04-09 16:02:06 +02:00
|
|
|
#include <utils/itemviews.h>
|
2015-01-13 09:08:41 +01:00
|
|
|
#include <utils/treemodel.h>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2014-01-03 12:53:55 +01:00
|
|
|
#include <QDebug>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDir>
|
2014-01-03 12:53:55 +01:00
|
|
|
#include <QGridLayout>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QHeaderView>
|
2015-01-13 09:08:41 +01:00
|
|
|
#include <QSet>
|
|
|
|
|
#include <QItemSelectionModel>
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\class ExtensionSystem::PluginView
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The PluginView class implements a widget that shows a list of all
|
|
|
|
|
plugins and their state.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2013-09-06 11:46:55 +02:00
|
|
|
This class can be embedded for example in a dialog in the application that
|
2008-12-02 12:01:29 +01:00
|
|
|
uses the plugin manager.
|
2013-09-06 11:46:55 +02:00
|
|
|
The class also provides notifications for interaction with the list.
|
2008-12-02 12:01:29 +01:00
|
|
|
|
|
|
|
|
\sa ExtensionSystem::PluginDetailsView
|
|
|
|
|
\sa ExtensionSystem::PluginErrorView
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\fn void PluginView::currentPluginChanged(ExtensionSystem::PluginSpec *spec)
|
|
|
|
|
The current selection in the plugin list has changed to the
|
|
|
|
|
plugin corresponding to \a spec.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\fn void PluginView::pluginActivated(ExtensionSystem::PluginSpec *spec)
|
|
|
|
|
The plugin list entry corresponding to \a spec has been activated,
|
2013-09-06 11:46:55 +02:00
|
|
|
for example by a double-click.
|
2008-12-02 12:01:29 +01:00
|
|
|
*/
|
|
|
|
|
|
2010-12-16 11:25:28 +01:00
|
|
|
Q_DECLARE_METATYPE(ExtensionSystem::PluginSpec*)
|
|
|
|
|
Q_DECLARE_METATYPE(ExtensionSystem::PluginCollection*)
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
using namespace Utils;
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
namespace ExtensionSystem {
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
enum Columns { NameColumn, LoadedColumn, VersionColumn, VendorColumn, };
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
enum IconIndex { OkIcon, ErrorIcon, NotLoadedIcon };
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
static const QIcon &icon(int num)
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-01-13 09:08:41 +01:00
|
|
|
static QIcon icons[] = {
|
|
|
|
|
QIcon(QLatin1String(":/extensionsystem/images/ok.png")),
|
|
|
|
|
QIcon(QLatin1String(":/extensionsystem/images/error.png")),
|
|
|
|
|
QIcon(QLatin1String(":/extensionsystem/images/notloaded.png")),
|
|
|
|
|
};
|
|
|
|
|
return icons[num];
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
class PluginItem : public TreeItem
|
2008-12-02 12:01:29 +01:00
|
|
|
{
|
2015-01-13 09:08:41 +01:00
|
|
|
public:
|
|
|
|
|
PluginItem(PluginSpec *spec, PluginView *view)
|
|
|
|
|
: m_spec(spec), m_view(view)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
int columnCount() const { return 4; }
|
|
|
|
|
|
|
|
|
|
QVariant data(int column, int role) const
|
|
|
|
|
{
|
|
|
|
|
switch (column) {
|
|
|
|
|
case NameColumn:
|
|
|
|
|
if (role == Qt::DisplayRole)
|
|
|
|
|
return m_spec->name();
|
|
|
|
|
if (role == Qt::ToolTipRole)
|
|
|
|
|
return QDir::toNativeSeparators(m_spec->filePath());
|
|
|
|
|
if (role == Qt::DecorationRole) {
|
|
|
|
|
bool ok = !m_spec->hasError();
|
|
|
|
|
QIcon i = icon(ok ? OkIcon : ErrorIcon);
|
|
|
|
|
if (ok && m_spec->state() != PluginSpec::Running)
|
|
|
|
|
i = icon(NotLoadedIcon);
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case LoadedColumn:
|
|
|
|
|
if (!m_spec->isAvailableForHostPlatform()) {
|
|
|
|
|
if (role == Qt::CheckStateRole)
|
|
|
|
|
return Qt::Unchecked;
|
|
|
|
|
if (role == Qt::ToolTipRole)
|
|
|
|
|
return PluginView::tr("Plugin is not available on this platform.");
|
|
|
|
|
} else if (m_spec->isRequired()) {
|
|
|
|
|
if (role == Qt::CheckStateRole)
|
|
|
|
|
return Qt::Checked;
|
|
|
|
|
if (role == Qt::ToolTipRole)
|
|
|
|
|
return PluginView::tr("Plugin is required.");
|
|
|
|
|
} else {
|
|
|
|
|
if (role == Qt::CheckStateRole)
|
|
|
|
|
return m_spec->isEnabledInSettings() ? Qt::Checked : Qt::Unchecked;
|
|
|
|
|
if (role == Qt::ToolTipRole)
|
|
|
|
|
return PluginView::tr("Load on startup");
|
|
|
|
|
}
|
|
|
|
|
break;
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
case VersionColumn:
|
|
|
|
|
if (role == Qt::DisplayRole)
|
|
|
|
|
return QString::fromLatin1("%1 (%2)").arg(m_spec->version(), m_spec->compatVersion());
|
|
|
|
|
break;
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
case VendorColumn:
|
|
|
|
|
if (role == Qt::DisplayRole)
|
|
|
|
|
return m_spec->vendor();
|
|
|
|
|
break;
|
2010-03-12 16:02:23 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
return QVariant();
|
2013-02-09 12:45:46 +08:00
|
|
|
}
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
bool setData(int column, const QVariant &data, int role)
|
|
|
|
|
{
|
|
|
|
|
if (column == LoadedColumn && role == Qt::CheckStateRole) {
|
|
|
|
|
m_spec->setEnabled(data.toBool());
|
|
|
|
|
update();
|
|
|
|
|
parent()->update();
|
|
|
|
|
emit m_view->pluginSettingsChanged(m_spec);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
bool isEnabled() const
|
|
|
|
|
{
|
|
|
|
|
if (m_spec->isRequired() || !m_spec->isAvailableForHostPlatform())
|
|
|
|
|
return false;
|
|
|
|
|
foreach (PluginSpec *spec, m_view->m_pluginDependencies.value(m_spec))
|
|
|
|
|
if (!spec->isEnabledInSettings())
|
|
|
|
|
return false;
|
|
|
|
|
return true;
|
2010-03-12 16:02:23 +01:00
|
|
|
}
|
|
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
Qt::ItemFlags flags(int column) const
|
|
|
|
|
{
|
|
|
|
|
Qt::ItemFlags ret = Qt::ItemIsSelectable;
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
if (isEnabled())
|
|
|
|
|
ret |= Qt::ItemIsEnabled;
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
if (column == LoadedColumn) {
|
|
|
|
|
if (m_spec->isAvailableForHostPlatform() && !m_spec->isRequired())
|
|
|
|
|
ret |= Qt::ItemIsEditable | Qt ::ItemIsUserCheckable;
|
2010-03-12 16:02:23 +01:00
|
|
|
}
|
2010-06-07 10:25:39 +02:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
return ret;
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
public:
|
|
|
|
|
PluginSpec *m_spec; // Not owned.
|
|
|
|
|
PluginView *m_view; // Not owned.
|
|
|
|
|
};
|
2010-03-12 17:22:46 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
class CollectionItem : public TreeItem
|
2010-03-12 17:22:46 +01:00
|
|
|
{
|
2015-01-13 09:08:41 +01:00
|
|
|
public:
|
|
|
|
|
CollectionItem(const QString &name, QList<PluginSpec *> plugins, PluginView *view)
|
|
|
|
|
: m_name(name), m_plugins(plugins), m_view(view)
|
|
|
|
|
{
|
|
|
|
|
foreach (PluginSpec *spec, plugins)
|
|
|
|
|
appendChild(new PluginItem(spec, view));
|
|
|
|
|
}
|
2010-03-12 17:22:46 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
int columnCount() const { return 4; }
|
|
|
|
|
|
|
|
|
|
QVariant data(int column, int role) const
|
|
|
|
|
{
|
|
|
|
|
if (column == NameColumn) {
|
|
|
|
|
if (role == Qt::DisplayRole)
|
|
|
|
|
return m_name;
|
|
|
|
|
if (role == Qt::DecorationRole) {
|
|
|
|
|
foreach (PluginSpec *spec, m_plugins) {
|
|
|
|
|
if (spec->hasError())
|
|
|
|
|
return icon(ErrorIcon);
|
|
|
|
|
if (!spec->isEnabledInSettings())
|
|
|
|
|
return icon(NotLoadedIcon);
|
|
|
|
|
}
|
|
|
|
|
return icon(OkIcon);
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
if (column == LoadedColumn) {
|
|
|
|
|
if (role == Qt::ToolTipRole)
|
|
|
|
|
return PluginView::tr("Load on Startup");
|
|
|
|
|
if (role == Qt::CheckStateRole) {
|
|
|
|
|
int checkedCount = 0;
|
|
|
|
|
foreach (PluginSpec *spec, m_plugins) {
|
|
|
|
|
if (spec->isEnabledInSettings())
|
|
|
|
|
++checkedCount;
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
if (checkedCount == 0)
|
|
|
|
|
return Qt::Unchecked;
|
|
|
|
|
if (checkedCount == m_plugins.length())
|
|
|
|
|
return Qt::Checked;
|
|
|
|
|
return Qt::PartiallyChecked;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
return QVariant();
|
|
|
|
|
}
|
2008-12-02 12:01:29 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
bool setData(int column, const QVariant &data, int role)
|
|
|
|
|
{
|
|
|
|
|
if (column == LoadedColumn && role == Qt::CheckStateRole) {
|
|
|
|
|
foreach (TreeItem *item, children())
|
|
|
|
|
static_cast<PluginItem *>(item)->setData(column, data, role);
|
|
|
|
|
update();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Qt::ItemFlags flags(int column) const
|
|
|
|
|
{
|
|
|
|
|
Qt::ItemFlags ret = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
|
|
|
|
if (column == LoadedColumn)
|
|
|
|
|
ret |= Qt::ItemIsEditable | Qt::ItemIsUserCheckable;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
QString m_name;
|
|
|
|
|
QList<PluginSpec *> m_plugins;
|
|
|
|
|
PluginView *m_view; // Not owned.
|
|
|
|
|
};
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
/*!
|
|
|
|
|
Constructs a PluginView that gets the list of plugins from the
|
|
|
|
|
given plugin \a manager with a given \a parent widget.
|
|
|
|
|
*/
|
|
|
|
|
PluginView::PluginView(QWidget *parent)
|
|
|
|
|
: QWidget(parent)
|
2010-03-12 16:02:23 +01:00
|
|
|
{
|
2015-01-13 09:08:41 +01:00
|
|
|
m_categoryView = new TreeView(this);
|
|
|
|
|
m_categoryView->setAlternatingRowColors(true);
|
|
|
|
|
m_categoryView->setIndentation(20);
|
|
|
|
|
m_categoryView->setUniformRowHeights(true);
|
|
|
|
|
m_categoryView->setSortingEnabled(true);
|
|
|
|
|
m_categoryView->setColumnWidth(LoadedColumn, 40);
|
|
|
|
|
m_categoryView->header()->setDefaultSectionSize(120);
|
|
|
|
|
m_categoryView->header()->setMinimumSectionSize(35);
|
2015-02-03 23:56:02 +02:00
|
|
|
m_categoryView->setActivationMode(DoubleClickActivation);
|
2015-01-13 09:08:41 +01:00
|
|
|
m_categoryView->setSelectionMode(QAbstractItemView::SingleSelection);
|
|
|
|
|
m_categoryView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
|
|
|
|
|
|
|
|
|
m_model = new TreeModel(this);
|
2015-01-16 15:24:53 +01:00
|
|
|
m_model->setHeader(QStringList() << tr("Name") << tr("Load") << tr("Version") << tr("Vendor"));
|
2015-01-13 09:08:41 +01:00
|
|
|
m_categoryView->setModel(m_model);
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
QGridLayout *gridLayout = new QGridLayout(this);
|
|
|
|
|
gridLayout->setContentsMargins(2, 2, 2, 2);
|
|
|
|
|
gridLayout->addWidget(m_categoryView, 1, 0, 1, 1);
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
QHeaderView *header = m_categoryView->header();
|
|
|
|
|
header->setSectionResizeMode(0, QHeaderView::ResizeToContents);
|
|
|
|
|
header->setSectionResizeMode(2, QHeaderView::ResizeToContents);
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
connect(PluginManager::instance(), &PluginManager::pluginsChanged,
|
|
|
|
|
this, &PluginView::updatePlugins);
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
connect(m_categoryView, &QAbstractItemView::activated,
|
|
|
|
|
[this](const QModelIndex &idx) { pluginActivated(pluginForIndex(idx)); });
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
connect(m_categoryView->selectionModel(), &QItemSelectionModel::currentChanged,
|
|
|
|
|
[this](const QModelIndex &idx) { currentPluginChanged(pluginForIndex(idx)); });
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
updatePlugins();
|
|
|
|
|
}
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
/*!
|
|
|
|
|
\internal
|
|
|
|
|
*/
|
|
|
|
|
PluginView::~PluginView()
|
|
|
|
|
{
|
|
|
|
|
}
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
/*!
|
|
|
|
|
Returns the current selection in the list of plugins.
|
|
|
|
|
*/
|
|
|
|
|
PluginSpec *PluginView::currentPlugin() const
|
|
|
|
|
{
|
|
|
|
|
return pluginForIndex(m_categoryView->currentIndex());
|
|
|
|
|
}
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
PluginSpec *PluginView::pluginForIndex(const QModelIndex &index) const
|
|
|
|
|
{
|
|
|
|
|
auto item = dynamic_cast<PluginItem *>(m_model->itemFromIndex(index));
|
|
|
|
|
return item ? item->m_spec: 0;
|
|
|
|
|
}
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
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);
|
2010-03-12 16:02:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
void PluginView::updatePlugins()
|
2010-03-12 16:02:23 +01:00
|
|
|
{
|
2015-01-13 09:08:41 +01:00
|
|
|
// Dependencies.
|
|
|
|
|
m_pluginDependencies.clear();
|
2012-06-18 11:34:15 +02:00
|
|
|
foreach (PluginSpec *spec, PluginManager::loadQueue()) {
|
2015-01-13 09:08:41 +01:00
|
|
|
QSet<PluginSpec *> deps;
|
|
|
|
|
queryDependendPlugins(spec, &deps);
|
|
|
|
|
m_pluginDependencies[spec] = deps;
|
|
|
|
|
}
|
2010-06-07 10:25:39 +02:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
// Model.
|
|
|
|
|
m_model->removeItems();
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
PluginCollection *defaultCollection = 0;
|
|
|
|
|
QList<CollectionItem *> collections;
|
|
|
|
|
foreach (PluginCollection *collection, PluginManager::pluginCollections()) {
|
|
|
|
|
if (collection->name().isEmpty() || collection->plugins().isEmpty()) {
|
|
|
|
|
defaultCollection = collection;
|
2010-05-19 16:29:47 +02:00
|
|
|
continue;
|
2015-01-13 09:08:41 +01:00
|
|
|
}
|
|
|
|
|
collections.append(new CollectionItem(collection->name(), collection->plugins(), this));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<PluginSpec *> plugins;
|
|
|
|
|
if (defaultCollection)
|
|
|
|
|
plugins = defaultCollection->plugins();
|
2010-03-12 16:02:23 +01:00
|
|
|
|
2015-01-13 09:08:41 +01:00
|
|
|
if (!plugins.isEmpty()) {
|
|
|
|
|
// add all non-categorized plugins into utilities. could also be added as root items
|
|
|
|
|
// but that makes the tree ugly.
|
|
|
|
|
collections.append(new CollectionItem(tr("Utilities"), plugins, this));
|
2010-03-12 16:02:23 +01:00
|
|
|
}
|
2015-01-13 09:08:41 +01:00
|
|
|
|
|
|
|
|
Utils::sort(collections, [](CollectionItem *a, CollectionItem *b) -> bool
|
|
|
|
|
{ return a->m_name < b->m_name; });
|
|
|
|
|
|
|
|
|
|
foreach (CollectionItem *collection, collections)
|
|
|
|
|
m_model->rootItem()->appendChild(collection);
|
|
|
|
|
|
|
|
|
|
m_model->layoutChanged();
|
|
|
|
|
m_categoryView->expandAll();
|
2008-12-02 12:01:29 +01:00
|
|
|
}
|
2015-01-13 09:08:41 +01:00
|
|
|
|
|
|
|
|
} // namespace ExtensionSystem
|