summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMikaël Capelle <capelle.mikael@gmail.com>2020-09-29 22:47:38 +0200
committerMikaël Capelle <capelle.mikael@gmail.com>2020-09-29 22:47:38 +0200
commit4b1a89648fffea98b447e4289dbc559d717d0b52 (patch)
treefdd1801b88fd03453d799a2dc7a6f82226087309 /src
parente9be288f7ce6ed7861a5ed381e2e16ae730524ad (diff)
Display plugins in a tree instead of a list in the settings dialog.
Diffstat (limited to 'src')
-rw-r--r--src/plugincontainer.cpp89
-rw-r--r--src/plugincontainer.h43
-rw-r--r--src/settingsdialog.cpp2
-rw-r--r--src/settingsdialog.ui12
-rw-r--r--src/settingsdialogplugins.cpp73
-rw-r--r--src/settingsdialogplugins.h8
6 files changed, 144 insertions, 83 deletions
diff --git a/src/plugincontainer.cpp b/src/plugincontainer.cpp
index 90a7e95f..60acc63c 100644
--- a/src/plugincontainer.cpp
+++ b/src/plugincontainer.cpp
@@ -34,6 +34,55 @@ template <> struct PluginTypeName<MOBase::IPluginTool> { static QString value()
template <> struct PluginTypeName<MOBase::IPluginProxy> { static QString value() { return QT_TR_NOOP("Proxy"); } };
template <> struct PluginTypeName<MOBase::IPluginFileMapper> { static QString value() { return QT_TR_NOOP("File Mapper"); } };
+
+QStringList PluginContainer::pluginInterfaces()
+{
+ // Find all the names:
+ QStringList names;
+ boost::mp11::mp_for_each<PluginTypeOrder>([&names](const auto* p) {
+ using plugin_type = std::decay_t<decltype(*p)>;
+ auto name = PluginTypeName<plugin_type>::value();
+ if (!name.isEmpty()) {
+ names.append(name);
+ }
+ });
+
+ return names;
+}
+
+
+PluginContainer::PluginContainer(OrganizerCore *organizer)
+ : m_Organizer(organizer)
+ , m_UserInterface(nullptr)
+{
+}
+
+PluginContainer::~PluginContainer() {
+ m_Organizer = nullptr;
+ unloadPlugins();
+}
+
+
+void PluginContainer::setUserInterface(IUserInterface *userInterface, QWidget *widget)
+{
+ for (IPluginProxy *proxy : bf::at_key<IPluginProxy>(m_Plugins)) {
+ proxy->setParentWidget(widget);
+ }
+
+ if (userInterface != nullptr) {
+ for (IPluginModPage *modPage : bf::at_key<IPluginModPage>(m_Plugins)) {
+ userInterface->registerModPage(modPage);
+ }
+
+ for (IPluginTool *tool : bf::at_key<IPluginTool>(m_Plugins)) {
+ userInterface->registerPluginTool(tool);
+ }
+ }
+
+ m_UserInterface = userInterface;
+}
+
+
QStringList PluginContainer::implementedInterfaces(IPlugin* plugin) const
{
// We need a QObject to be able to qobject_cast<> to the plugin types:
@@ -45,7 +94,7 @@ QStringList PluginContainer::implementedInterfaces(IPlugin* plugin) const
// Find all the names:
QStringList names;
- boost::mp11::mp_for_each<PluginTypeOrder>([oPlugin, &names](const auto *p) {
+ boost::mp11::mp_for_each<PluginTypeOrder>([oPlugin, &names](const auto* p) {
using plugin_type = std::decay_t<decltype(*p)>;
if (qobject_cast<plugin_type*>(oPlugin)) {
auto name = PluginTypeName<plugin_type>::value();
@@ -53,7 +102,7 @@ QStringList PluginContainer::implementedInterfaces(IPlugin* plugin) const
names.append(name);
}
}
- });
+ });
// If the plugin implements at least one interface other than IPlugin, remove IPlugin:
if (names.size() > 1) {
@@ -63,6 +112,7 @@ QStringList PluginContainer::implementedInterfaces(IPlugin* plugin) const
return names;
}
+
QString PluginContainer::topImplementedInterface(IPlugin* plugin) const
{
// We need a QObject to be able to qobject_cast<> to the plugin types:
@@ -74,7 +124,7 @@ QString PluginContainer::topImplementedInterface(IPlugin* plugin) const
// Find all the names:
QString name;
- boost::mp11::mp_for_each<PluginTypeOrder>([oPlugin, &name](auto *p) {
+ boost::mp11::mp_for_each<PluginTypeOrder>([oPlugin, &name](auto* p) {
using plugin_type = std::decay_t<decltype(*p)>;
if (name.isEmpty() && qobject_cast<plugin_type*>(oPlugin)) {
auto tname = PluginTypeName<plugin_type>::value();
@@ -82,42 +132,11 @@ QString PluginContainer::topImplementedInterface(IPlugin* plugin) const
name = tname;
}
}
- });
+ });
return name;
}
-PluginContainer::PluginContainer(OrganizerCore *organizer)
- : m_Organizer(organizer)
- , m_UserInterface(nullptr)
-{
-}
-
-PluginContainer::~PluginContainer() {
- m_Organizer = nullptr;
- unloadPlugins();
-}
-
-
-void PluginContainer::setUserInterface(IUserInterface *userInterface, QWidget *widget)
-{
- for (IPluginProxy *proxy : bf::at_key<IPluginProxy>(m_Plugins)) {
- proxy->setParentWidget(widget);
- }
-
- if (userInterface != nullptr) {
- for (IPluginModPage *modPage : bf::at_key<IPluginModPage>(m_Plugins)) {
- userInterface->registerModPage(modPage);
- }
-
- for (IPluginTool *tool : bf::at_key<IPluginTool>(m_Plugins)) {
- userInterface->registerPluginTool(tool);
- }
- }
-
- m_UserInterface = userInterface;
-}
-
QStringList PluginContainer::pluginFileNames() const
{
diff --git a/src/plugincontainer.h b/src/plugincontainer.h
index 8672606b..07363ee7 100644
--- a/src/plugincontainer.h
+++ b/src/plugincontainer.h
@@ -72,26 +72,13 @@ private:
public:
/**
- * @brief Retrieved the (localized) names of interfaces implemented by the given
- * plugin.
+ * @brief Retrieved the (localized) names of the various plugin interfaces.
*
- * @param plugin The plugin to retrieve interface for.
- *
- * @return the (localized) names of interfaces implemented by this plugin.
+ * @return the (localized) names of the various plugin interfaces.
*/
- QStringList implementedInterfaces(MOBase::IPlugin *plugin) const;
+ static QStringList pluginInterfaces();
- /**
- * @brief Return the (localized) name of the most important interface implemented by
- * the given plugin.
- *
- * The order of interfaces is defined in X.
- *
- * @param plugin The plugin to retrieve the interface for.
- *
- * @return the (localized) name of the most important interface implemented by this plugin.
- */
- QString topImplementedInterface(MOBase::IPlugin* plugin) const;
+public:
PluginContainer(OrganizerCore *organizer);
virtual ~PluginContainer();
@@ -126,6 +113,28 @@ public:
}
/**
+ * @brief Retrieved the (localized) names of interfaces implemented by the given
+ * plugin.
+ *
+ * @param plugin The plugin to retrieve interface for.
+ *
+ * @return the (localized) names of interfaces implemented by this plugin.
+ */
+ QStringList implementedInterfaces(MOBase::IPlugin* plugin) const;
+
+ /**
+ * @brief Return the (localized) name of the most important interface implemented by
+ * the given plugin.
+ *
+ * The order of interfaces is defined in X.
+ *
+ * @param plugin The plugin to retrieve the interface for.
+ *
+ * @return the (localized) name of the most important interface implemented by this plugin.
+ */
+ QString topImplementedInterface(MOBase::IPlugin* plugin) const;
+
+ /**
* @return the preview generator.
*/
const PreviewGenerator &previewGenerator() const;
diff --git a/src/settingsdialog.cpp b/src/settingsdialog.cpp
index daccfba9..87c7201d 100644
--- a/src/settingsdialog.cpp
+++ b/src/settingsdialog.cpp
@@ -43,7 +43,7 @@ SettingsDialog::SettingsDialog(PluginContainer *pluginContainer, Settings& setti
m_tabs.push_back(std::unique_ptr<SettingsTab>(new DiagnosticsSettingsTab(settings, *this)));
m_tabs.push_back(std::unique_ptr<SettingsTab>(new NexusSettingsTab(settings, *this)));
m_tabs.push_back(std::unique_ptr<SettingsTab>(new SteamSettingsTab(settings, *this)));
- m_tabs.push_back(std::unique_ptr<SettingsTab>(new PluginsSettingsTab(settings, *this)));
+ m_tabs.push_back(std::unique_ptr<SettingsTab>(new PluginsSettingsTab(settings, m_pluginContainer, *this)));
m_tabs.push_back(std::unique_ptr<SettingsTab>(new WorkaroundsSettingsTab(settings, *this)));
}
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index 2ceb91db..97fa01bd 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -17,7 +17,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
- <number>0</number>
+ <number>4</number>
</property>
<widget class="QWidget" name="generalTab">
<attribute name="title">
@@ -1042,16 +1042,18 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
- <widget class="QListWidget" name="pluginsList">
+ <widget class="QTreeWidget" name="pluginsList">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
- <property name="sortingEnabled">
- <bool>true</bool>
- </property>
+ <column>
+ <property name="text">
+ <string notr="true">1</string>
+ </property>
+ </column>
</widget>
</item>
<item>
diff --git a/src/settingsdialogplugins.cpp b/src/settingsdialogplugins.cpp
index 41430f1f..cb306f36 100644
--- a/src/settingsdialogplugins.cpp
+++ b/src/settingsdialogplugins.cpp
@@ -3,33 +3,57 @@
#include "noeditdelegate.h"
#include <iplugin.h>
+#include "plugincontainer.h"
+
using MOBase::IPlugin;
-PluginsSettingsTab::PluginsSettingsTab(Settings& s, SettingsDialog& d)
+PluginsSettingsTab::PluginsSettingsTab(Settings& s, PluginContainer* pluginContainer, SettingsDialog& d)
: SettingsTab(s, d)
{
ui->pluginSettingsList->setStyleSheet("QTreeWidget::item {padding-right: 10px;}");
+ // Create top-level tree widget:
+ QStringList pluginInterfaces = pluginContainer->pluginInterfaces();
+ pluginInterfaces.sort(Qt::CaseInsensitive);
+ std::map<QString, QTreeWidgetItem*> topItems;
+ for (QString interfaceName : pluginInterfaces) {
+ auto *item = new QTreeWidgetItem(ui->pluginsList, { interfaceName });
+ item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
+ auto font = item->font(0);
+ font.setBold(true);
+ item->setFont(0, font);
+ topItems[interfaceName] = item;
+ item->setExpanded(true);
+ }
+ ui->pluginsList->setHeaderHidden(true);
+
// display plugin settings
QSet<QString> handledNames;
for (IPlugin *plugin : settings().plugins().plugins()) {
if (handledNames.contains(plugin->name()))
continue;
- QListWidgetItem *listItem = new QListWidgetItem(plugin->localizedName(), ui->pluginsList);
- listItem->setData(ROLE_PLUGIN, QVariant::fromValue((void*)plugin));
- listItem->setData(ROLE_SETTINGS, settings().plugins().settings(plugin->name()));
- listItem->setData(ROLE_DESCRIPTIONS, settings().plugins().descriptions(plugin->name()));
- ui->pluginsList->addItem(listItem);
+ QTreeWidgetItem* listItem = new QTreeWidgetItem(
+ topItems.at(pluginContainer->topImplementedInterface(plugin)), { plugin->localizedName() });
+ listItem->setData(0, ROLE_PLUGIN, QVariant::fromValue((void*)plugin));
+ listItem->setData(0, ROLE_SETTINGS, settings().plugins().settings(plugin->name()));
+ listItem->setData(0, ROLE_DESCRIPTIONS, settings().plugins().descriptions(plugin->name()));
+
+ if (handledNames.isEmpty()) {
+ listItem->setSelected(true);
+ }
+
handledNames.insert(plugin->name());
}
+ ui->pluginsList->sortByColumn(0, Qt::AscendingOrder);
+
// display plugin blacklist
for (const QString &pluginName : settings().plugins().blacklist()) {
ui->pluginBlacklist->addItem(pluginName);
}
QObject::connect(
- ui->pluginsList, &QListWidget::currentItemChanged,
+ ui->pluginsList, &QTreeWidget::currentItemChanged,
[&](auto* current, auto* previous) { on_pluginsList_currentItemChanged(current, previous); });
QShortcut *delShortcut = new QShortcut(
@@ -37,18 +61,21 @@ PluginsSettingsTab::PluginsSettingsTab(Settings& s, SettingsDialog& d)
QObject::connect(delShortcut, &QShortcut::activated, &dialog(), [&]{ deleteBlacklistItem(); });
}
-IPlugin* PluginsSettingsTab::plugin(QListWidgetItem* pluginItem) const
+IPlugin* PluginsSettingsTab::plugin(QTreeWidgetItem* pluginItem) const
{
- return static_cast<IPlugin*>(qvariant_cast<void*>(pluginItem->data(ROLE_PLUGIN)));
+ return static_cast<IPlugin*>(qvariant_cast<void*>(pluginItem->data(0, ROLE_PLUGIN)));
}
void PluginsSettingsTab::update()
{
// transfer plugin settings to in-memory structure
- for (int i = 0; i < ui->pluginsList->count(); ++i) {
- QListWidgetItem *item = ui->pluginsList->item(i);
- settings().plugins().setSettings(
- plugin(item)->name(), item->data(ROLE_SETTINGS).toMap());
+ for (int i = 0; i < ui->pluginsList->topLevelItemCount(); ++i) {
+ auto *topLevelItem = ui->pluginsList->topLevelItem(i);
+ for (int j = 0; j < topLevelItem->childCount(); ++j) {
+ auto* item = topLevelItem->child(j);
+ settings().plugins().setSettings(
+ plugin(item)->name(), item->data(0, ROLE_SETTINGS).toMap());
+ }
}
// set plugin blacklist
@@ -67,18 +94,22 @@ void PluginsSettingsTab::closing()
storeSettings(ui->pluginsList->currentItem());
}
-void PluginsSettingsTab::on_pluginsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous)
+void PluginsSettingsTab::on_pluginsList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
{
storeSettings(previous);
+ if (!current->data(0, ROLE_PLUGIN).isValid()) {
+ return;
+ }
+
ui->pluginSettingsList->clear();
- IPlugin *plugin = static_cast<IPlugin*>(current->data(Qt::UserRole).value<void*>());
+ IPlugin* plugin = this->plugin(current);
ui->authorLabel->setText(plugin->author());
ui->versionLabel->setText(plugin->version().canonicalString());
ui->descriptionLabel->setText(plugin->description());
- QVariantMap settings = current->data(ROLE_SETTINGS).toMap();
- QVariantMap descriptions = current->data(ROLE_DESCRIPTIONS).toMap();
+ QVariantMap settings = current->data(0, ROLE_SETTINGS).toMap();
+ QVariantMap descriptions = current->data(0, ROLE_DESCRIPTIONS).toMap();
ui->pluginSettingsList->setEnabled(settings.count() != 0);
for (auto iter = settings.begin(); iter != settings.end(); ++iter) {
QTreeWidgetItem *newItem = new QTreeWidgetItem(QStringList(iter.key()));
@@ -109,16 +140,16 @@ void PluginsSettingsTab::deleteBlacklistItem()
ui->pluginBlacklist->takeItem(ui->pluginBlacklist->currentIndex().row());
}
-void PluginsSettingsTab::storeSettings(QListWidgetItem *pluginItem)
+void PluginsSettingsTab::storeSettings(QTreeWidgetItem *pluginItem)
{
- if (pluginItem != nullptr) {
- QVariantMap settings = pluginItem->data(ROLE_SETTINGS).toMap();
+ if (pluginItem != nullptr && pluginItem->data(0, ROLE_PLUGIN).isValid()) {
+ QVariantMap settings = pluginItem->data(0, ROLE_SETTINGS).toMap();
for (int i = 0; i < ui->pluginSettingsList->topLevelItemCount(); ++i) {
const QTreeWidgetItem *item = ui->pluginSettingsList->topLevelItem(i);
settings[item->text(0)] = item->data(1, Qt::DisplayRole);
}
- pluginItem->setData(ROLE_SETTINGS, settings);
+ pluginItem->setData(0, ROLE_SETTINGS, settings);
}
}
diff --git a/src/settingsdialogplugins.h b/src/settingsdialogplugins.h
index b793e5fd..f9069be1 100644
--- a/src/settingsdialogplugins.h
+++ b/src/settingsdialogplugins.h
@@ -7,21 +7,21 @@
class PluginsSettingsTab : public SettingsTab
{
public:
- PluginsSettingsTab(Settings& settings, SettingsDialog& dialog);
+ PluginsSettingsTab(Settings& settings, PluginContainer* pluginContainer, SettingsDialog& dialog);
void update();
void closing() override;
private:
- void on_pluginsList_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous);
+ void on_pluginsList_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
void deleteBlacklistItem();
- void storeSettings(QListWidgetItem *pluginItem);
+ void storeSettings(QTreeWidgetItem *pluginItem);
/**
* @brief Retrieve the plugin associated to the given item in the list.
*
*/
- MOBase::IPlugin* plugin(QListWidgetItem *pluginItem) const;
+ MOBase::IPlugin* plugin(QTreeWidgetItem *pluginItem) const;
constexpr static int ROLE_PLUGIN = Qt::UserRole;
constexpr static int ROLE_SETTINGS = Qt::UserRole + 1;