From 7dce10c342edaf48b73ffa0064a07ce1936629a9 Mon Sep 17 00:00:00 2001 From: Alan Garny Date: Wed, 12 Feb 2020 15:26:06 +1300 Subject: [PATCH] Plugins and preferences dialog: improved our use of tree views. This is part of our work on issue #2285. --- CMakeLists.txt | 1 + src/misc/plugincategoryitem.cpp.inl | 14 +- src/pluginitemmodel.cpp | 322 ++++++++++++++++++++++++++++ src/pluginitemmodel.h | 118 ++++++++++ src/pluginsdialog.cpp | 82 +++---- src/pluginsdialog.h | 20 +- src/preferencesdialog.cpp | 22 +- src/preferencesdialog.h | 14 +- 8 files changed, 511 insertions(+), 82 deletions(-) create mode 100644 src/pluginitemmodel.cpp create mode 100644 src/pluginitemmodel.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1867a50c3e..57a5c9bb17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -646,6 +646,7 @@ set(SOURCES src/generalpreferenceswidget.cpp src/main.cpp src/mainwindow.cpp + src/pluginitemmodel.cpp src/pluginsdialog.cpp src/preferencesdialog.cpp src/splashscreenwindow.cpp diff --git a/src/misc/plugincategoryitem.cpp.inl b/src/misc/plugincategoryitem.cpp.inl index f718d369a0..4b6944be29 100644 --- a/src/misc/plugincategoryitem.cpp.inl +++ b/src/misc/plugincategoryitem.cpp.inl @@ -1,31 +1,31 @@ // Return the given category item, after having created it, if it didn't // already exist - QStandardItem *res = mCategoryItems.value(pCategory); + PluginItem *res = mCategoryItems.value(pCategory); if (res == nullptr) { // No category item exists for the given category, so create one and add // it to our data model (and this in the right place) bool inserted = false; - QStandardItem *rootItem = mModel->invisibleRootItem(); + PluginItem *rootItem = mModel->invisibleRootItem(); QString categoryName = pluginCategoryName(pCategory); QString nonDiacriticCategoryName = nonDiacriticString(categoryName); - res = new QStandardItem(categoryName); + res = new PluginItem(categoryName); - for (int i = 0, iMax = rootItem->rowCount(); i < iMax; ++i) { - if (nonDiacriticCategoryName < nonDiacriticString(rootItem->child(i)->text())) { + for (int i = 0, iMax = rootItem->childCount(); i < iMax; ++i) { + if (nonDiacriticCategoryName < nonDiacriticString(rootItem->child(i)->name())) { inserted = true; - mModel->invisibleRootItem()->insertRow(i, res); + mModel->invisibleRootItem()->insert(i, res); break; } } if (!inserted) { - mModel->invisibleRootItem()->appendRow(res); + mModel->invisibleRootItem()->append(res); } // Keep track of the relationship between our new item and its category diff --git a/src/pluginitemmodel.cpp b/src/pluginitemmodel.cpp new file mode 100644 index 0000000000..7846182e9e --- /dev/null +++ b/src/pluginitemmodel.cpp @@ -0,0 +1,322 @@ +/******************************************************************************* + +Copyright (C) The University of Auckland + +OpenCOR is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +OpenCOR is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*******************************************************************************/ + +//============================================================================== +// Plugin item model +//============================================================================== + +#include "pluginitemmodel.h" + +//============================================================================== + +namespace OpenCOR { + +//============================================================================== + +PluginItem::PluginItem(const QIcon &pIcon, const QString &pName) + : mIcon(pIcon), + mName(pName) +{ +} + +//============================================================================== + +PluginItem::PluginItem(const QString &pName) + : PluginItem(QIcon(), pName) +{ +} + +//============================================================================== + +PluginItem::~PluginItem() +{ + // Delete some internal objects + + qDeleteAll(mChildren); +} + +//============================================================================== + +void PluginItem::setParentAndModel(PluginItem *pParent, PluginItemModel *pModel) +{ + // Set our parent and our model + + mParent = pParent; + mModel = pModel; +} + +//============================================================================== + +PluginItem * PluginItem::parent() const +{ + // Return our parent + + return mParent; +} + +//============================================================================== + +PluginItem * PluginItem::child(int pIndex) const +{ + // Return the requested child + + return mChildren.value(pIndex); +} + +//============================================================================== + +int PluginItem::childCount() const +{ + // Return our number of children + + return mChildren.count(); +} + +//============================================================================== + +bool PluginItem::hasChildren() const +{ + // Return whether we have children + + return !mChildren.isEmpty(); +} + +//============================================================================== + +int PluginItem::index() const +{ + // Return our index + + if (mParent != nullptr) { + return mParent->mChildren.indexOf(const_cast(this)); + } + + return -1; +} + +//============================================================================== + +QModelIndex PluginItem::modelIndex() const +{ + // Return our model index + + return mModel->createIndex(index(), mParent); +} + +//============================================================================== + +bool PluginItem::isCheckable() const +{ + // Return whether we are checkable + + return mCheckable; +} + +//============================================================================== + +void PluginItem::setCheckable(bool pCheckable) +{ + // Specify whether we are checkable + + mCheckable = pCheckable; +} + +//============================================================================== + +Qt::CheckState PluginItem::checkState() const +{ + // Return our check state + + return mCheckState; +} + +//============================================================================== + +void PluginItem::setCheckState(Qt::CheckState pCheckState) +{ + // Set our check state + + mCheckState = pCheckState; +} + +//============================================================================== + +QString PluginItem::name() const +{ + // Return our name + + return mName; +} + +//============================================================================== + +void PluginItem::insert(int pIndex, PluginItem *pItem) +{ + // Insert the given item before the given index in our list of children + + pItem->setParentAndModel(this, mModel); + + mChildren.insert(pIndex, pItem); +} + +//============================================================================== + +void PluginItem::append(PluginItem *pItem) +{ + // Append the given item to our list of children + + pItem->setParentAndModel(this, mModel); + + mChildren << pItem; +} + +//============================================================================== + +PluginItemModel::PluginItemModel(QObject *pParent) + : QAbstractItemModel(pParent), + mRootItem(new PluginItem()) +{ + mRootItem->setParentAndModel(nullptr, this); +} + +//============================================================================== + +PluginItemModel::~PluginItemModel() +{ + // Delete some internal objects + + delete mRootItem; +} + +//============================================================================== + +QModelIndex PluginItemModel::index(int pRow, int pColumn, + const QModelIndex &pParent) const +{ + Q_UNUSED(pColumn) + + // Return the index of the item at the given row in the given parent + + if ((pRow < 0) || (pRow >= rowCount(pParent))) { + return {}; + } + + PluginItem *childItem = (pParent.isValid()? + static_cast(pParent.internalPointer()): + mRootItem)->child(pRow); + + if (childItem != nullptr) { + return createIndex(pRow, childItem); + } + + return {}; +} + +//============================================================================== + +QModelIndex PluginItemModel::parent(const QModelIndex &pChild) const +{ + // Return the parent of the given child + + if (pChild.isValid()) { + PluginItem *parentItem = static_cast(pChild.internalPointer())->parent(); + + if ((parentItem != nullptr) && (parentItem != mRootItem)) { + return createIndex(parentItem->index(), parentItem); + } + } + + return {}; +} + +//============================================================================== + +int PluginItemModel::rowCount(const QModelIndex &pParent) const +{ + // Return the number of rows for the given parent + + if (pParent.isValid()) { + return static_cast(pParent.internalPointer())->childCount(); + } + + return mRootItem->childCount(); +} + +//============================================================================== + +int PluginItemModel::columnCount(const QModelIndex &pParent) const +{ + Q_UNUSED(pParent) + + // Return the number of columns for the given parent, i.e. always one + + return 1; +} + +//============================================================================== + +QVariant PluginItemModel::data(const QModelIndex &pIndex, int pRole) const +{ + // Return the data for the given index + + if (pIndex.isValid() && (pRole == Qt::DisplayRole)) { + return static_cast(pIndex.internalPointer())->name(); + } + + return {}; +} + +//============================================================================== + +PluginItem * PluginItemModel::invisibleRootItem() const +{ + // Return our invisible root item + + return mRootItem; +} + +//============================================================================== + +PluginItem * PluginItemModel::itemFromIndex(const QModelIndex &pIndex) const +{ + // Return the item at the given index + + if (pIndex.isValid()) { + return static_cast(pIndex.internalPointer()); + } + + return nullptr; +} + +//============================================================================== + +QModelIndex PluginItemModel::createIndex(int pRow, PluginItem *pParent) const +{ + // Create and return the inde for the given row and parent + + return QAbstractItemModel::createIndex(pRow, 0, pParent); +} + +//============================================================================== + +} // namespace OpenCOR + +//============================================================================== +// End of file +//============================================================================== diff --git a/src/pluginitemmodel.h b/src/pluginitemmodel.h new file mode 100644 index 0000000000..95fd94c224 --- /dev/null +++ b/src/pluginitemmodel.h @@ -0,0 +1,118 @@ +/******************************************************************************* + +Copyright (C) The University of Auckland + +OpenCOR is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +OpenCOR is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . + +*******************************************************************************/ + +//============================================================================== +// Plugin item model +//============================================================================== + +#pragma once + +//============================================================================== + +#include +#include + +//============================================================================== + +namespace OpenCOR { + +//============================================================================== + +class PluginItemModel; + +//============================================================================== + +class PluginItem +{ +public: + explicit PluginItem(const QIcon &pIcon, const QString &pName); + explicit PluginItem(const QString &pName = QString()); + ~PluginItem(); + + void setParentAndModel(PluginItem *pParent, PluginItemModel *pModel); + + PluginItem * parent() const; + PluginItem * child(int pIndex) const; + + int childCount() const; + bool hasChildren() const; + + int index() const; + + QModelIndex modelIndex() const; + + bool isCheckable() const; + void setCheckable(bool pCheckable); + + Qt::CheckState checkState() const; + void setCheckState(Qt::CheckState pCheckState); + + QString name() const; + + void insert(int pIndex, PluginItem *pItem); + void append(PluginItem *pItem); + +private: + PluginItemModel *mModel = nullptr; + + PluginItem *mParent = nullptr; + QVector mChildren; + + bool mCheckable = true; + Qt::CheckState mCheckState; + + QIcon mIcon; + QString mName; +}; + +//============================================================================== + +class PluginItemModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit PluginItemModel(QObject *pParent); + ~PluginItemModel() override; + + QModelIndex index(int pRow, int pColumn, + const QModelIndex &pParent = {}) const override; + QModelIndex parent(const QModelIndex &pChild) const override; + int rowCount(const QModelIndex &pParent = {}) const override; + int columnCount(const QModelIndex &pParent = {}) const override; + QVariant data(const QModelIndex &pIndex, + int pRole = Qt::DisplayRole) const override; + + PluginItem * invisibleRootItem() const; + + PluginItem * itemFromIndex(const QModelIndex &pIndex) const; + + QModelIndex createIndex(int pRow, PluginItem *pParent) const; + +private: + PluginItem *mRootItem; +}; + +//============================================================================== + +} // namespace OpenCOR + +//============================================================================== +// End of file +//============================================================================== diff --git a/src/pluginsdialog.cpp b/src/pluginsdialog.cpp index 10590ced34..9a0b388f7f 100644 --- a/src/pluginsdialog.cpp +++ b/src/pluginsdialog.cpp @@ -25,6 +25,7 @@ along with this program. If not, see . #include "guiutils.h" #include "mainwindow.h" #include "plugin.h" +#include "pluginitemmodel.h" #include "pluginmanager.h" #include "pluginsdialog.h" @@ -39,7 +40,6 @@ along with this program. If not, see . #include #include #include -#include #include //============================================================================== @@ -62,13 +62,13 @@ void PluginItemDelegate::paint(QPainter *pPainter, // Paint the item as normal, if it is selectable, as disabled, if it isn't // selectable, or bold, if it is a category - QStandardItem *pluginItem = qobject_cast(pIndex.model())->itemFromIndex(pIndex); - + const PluginItemModel *pluginItemModel = qobject_cast(pIndex.model()); + PluginItem *pluginItem = pluginItemModel->itemFromIndex(pIndex); QStyleOptionViewItem option(pOption); initStyleOption(&option, pIndex); - if (pluginItem->parent() != nullptr) { + if (pluginItem->parent() != pluginItemModel->invisibleRootItem()) { if (!pluginItem->isCheckable()) { option.state &= ~QStyle::State_Enabled; } @@ -134,7 +134,7 @@ PluginsDialog::PluginsDialog(PluginManager *pPluginManager, // plugins that are shown as 'disabled' (to reflect the fact that users // cannot decide whether they should be loaded) - mModel = new QStandardItemModel(this); + mModel = new PluginItemModel(this); #ifdef Q_OS_MAC mGui->treeView->setAttribute(Qt::WA_MacShowFocusRect, false); @@ -150,8 +150,8 @@ PluginsDialog::PluginsDialog(PluginManager *pPluginManager, for (auto plugin : mPluginManager->sortedPlugins()) { // Create the item corresponding to the current plugin - auto pluginItem = new QStandardItem((plugin->status() == Plugin::Status::Loaded)?LoadedIcon:NotLoadedIcon, - plugin->name()); + auto pluginItem = new PluginItem((plugin->status() == Plugin::Status::Loaded)?LoadedIcon:NotLoadedIcon, + plugin->name()); // Only selectable plugins and plugins that are of the right type are // checkable @@ -181,19 +181,19 @@ PluginsDialog::PluginsDialog(PluginManager *pPluginManager, // Add the plugin to its corresponding category - pluginCategoryItem(pluginInfo->category())->appendRow(pluginItem); + pluginCategoryItem(pluginInfo->category())->append(pluginItem); } else { // We are either dealing with a library that is not a plugin or with // a plugin that is too old, so add it to the Invalid category - pluginCategoryItem(PluginInfo::Category::Invalid)->appendRow(pluginItem); + pluginCategoryItem(PluginInfo::Category::Invalid)->append(pluginItem); } } // Make a category checkable if it contains selectable plugins for (auto categoryItem : mCategoryItems) { - for (int i = 0, iMax = categoryItem->rowCount(); i < iMax; ++i) { + for (int i = 0, iMax = categoryItem->childCount(); i < iMax; ++i) { if (categoryItem->child(i)->isCheckable()) { categoryItem->setCheckable(true); @@ -323,9 +323,9 @@ void PluginsDialog::updateInformation(const QModelIndex &pNewIndex, // Update the information view with the category's or plugin's information - QStandardItem *item = pNewIndex.isValid()?mModel->itemFromIndex(pNewIndex):nullptr; - QString itemText = (item != nullptr)?item->text():QString(); - Plugin *plugin = ((item != nullptr) && (item->parent() != nullptr))?mPluginManager->plugin(itemText):nullptr; + PluginItem *item = pNewIndex.isValid()?mModel->itemFromIndex(pNewIndex):nullptr; + QString itemName = (item != nullptr)?item->name():QString(); + Plugin *plugin = ((item != nullptr) && (item->parent() != nullptr))?mPluginManager->plugin(itemName):nullptr; if (plugin != nullptr) { // We are supposedly dealing with a plugin, so retrieve its information, @@ -400,7 +400,7 @@ void PluginsDialog::updateInformation(const QModelIndex &pNewIndex, // The category's name mGui->fieldOneLabel->setText(tr("Category:")); - mGui->fieldOneValue->setText(itemText); + mGui->fieldOneValue->setText(itemName); // The category's description @@ -429,23 +429,17 @@ void PluginsDialog::updateInformation(const QModelIndex &pNewIndex, //============================================================================== -void PluginsDialog::updatePluginsSelectedState(QStandardItem *pItem, +void PluginsDialog::updatePluginsSelectedState(PluginItem *pItem, bool pInitializing) { - // Disable the connection that handles a change in a plugin's loading state - // (otherwise what we are doing here is going to be completely uneffective) - - disconnect(mModel, &QStandardItemModel::itemChanged, - this, QOverload::of(&PluginsDialog::updatePluginsSelectedState)); - // In case we un/select a category, then go through its selectable plugins // and un/select them accordingly if ((pItem != nullptr) && (pItem->parent() == nullptr)) { Qt::CheckState newCheckState = (pItem->checkState() == Qt::Unchecked)?Qt::Unchecked:Qt::Checked; - for (int i = 0, iMax = pItem->rowCount(); i < iMax; ++i) { - QStandardItem *pluginItem = pItem->child(i); + for (int i = 0, iMax = pItem->childCount(); i < iMax; ++i) { + PluginItem *pluginItem = pItem->child(i); if (mSelectablePluginItems.contains(pluginItem)) { pluginItem->setCheckState(newCheckState); @@ -465,7 +459,7 @@ void PluginsDialog::updatePluginsSelectedState(QStandardItem *pItem, for (auto selectablePluginItem : mSelectablePluginItems) { if ( (selectablePluginItem->checkState() == Qt::Checked) - && (mPluginManager->plugin(selectablePluginItem->text())->info()->fullDependencies().contains(unselectablePluginItem->text()))) { + && (mPluginManager->plugin(selectablePluginItem->name())->info()->fullDependencies().contains(unselectablePluginItem->name()))) { unselectablePluginItem->setCheckState(Qt::Checked); break; @@ -477,7 +471,7 @@ void PluginsDialog::updatePluginsSelectedState(QStandardItem *pItem, // selectable plugin for (auto categoryItem : mCategoryItems) { - int nbOfPlugins = categoryItem->rowCount(); + int nbOfPlugins = categoryItem->childCount(); if (nbOfPlugins != 0) { int nbOfSelectablePlugins = 0; @@ -485,7 +479,7 @@ void PluginsDialog::updatePluginsSelectedState(QStandardItem *pItem, int nbOfSelectedSelectablePlugins = 0; for (int i = 0; i < nbOfPlugins; ++i) { - QStandardItem *pluginItem = categoryItem->child(i); + PluginItem *pluginItem = categoryItem->child(i); if (pluginItem->isCheckable()) { ++nbOfSelectablePlugins; @@ -515,7 +509,7 @@ void PluginsDialog::updatePluginsSelectedState(QStandardItem *pItem, // loading state of the plugins for (auto plugin : mSelectablePluginItems+mUnselectablePluginItems) { - mInitialLoadingStates.insert(plugin->text(), + mInitialLoadingStates.insert(plugin->name(), plugin->checkState() == Qt::Checked); } } @@ -523,7 +517,7 @@ void PluginsDialog::updatePluginsSelectedState(QStandardItem *pItem, bool buttonsEnabled = false; for (auto plugin : mSelectablePluginItems+mUnselectablePluginItems) { - if (mInitialLoadingStates.value(plugin->text()) != (plugin->checkState() == Qt::Checked)) { + if (mInitialLoadingStates.value(plugin->name()) != (plugin->checkState() == Qt::Checked)) { buttonsEnabled = true; break; @@ -532,17 +526,11 @@ void PluginsDialog::updatePluginsSelectedState(QStandardItem *pItem, mGui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(buttonsEnabled); mGui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(buttonsEnabled); - - // Re-enable the connection that handles a change in a plugin's loading - // state - - connect(mModel, &QStandardItemModel::itemChanged, - this, QOverload::of(&PluginsDialog::updatePluginsSelectedState)); } //============================================================================== -void PluginsDialog::updatePluginsSelectedState(QStandardItem *pItem) +void PluginsDialog::updatePluginsSelectedState(PluginItem *pItem) { // Update our plugins selected state @@ -565,7 +553,7 @@ void PluginsDialog::buttonBoxAccepted() // Keep track of the loading state of the various selectable plugins for (auto selectablePluginItem : mSelectablePluginItems) { - Plugin::setLoad(selectablePluginItem->text(), + Plugin::setLoad(selectablePluginItem->name(), selectablePluginItem->checkState() == Qt::Checked); } @@ -593,7 +581,7 @@ void PluginsDialog::apply() //============================================================================== -QStandardItem * PluginsDialog::pluginCategoryItem(PluginInfo::Category pCategory) +PluginItem * PluginsDialog::pluginCategoryItem(PluginInfo::Category pCategory) { #include "plugincategoryitem.cpp.inl" } @@ -620,8 +608,8 @@ void PluginsDialog::selectablePluginsCheckBoxToggled(bool pChecked) // Show/hide our unselectable plugins for (auto unselectablePluginItem : mUnselectablePluginItems) { - mGui->treeView->setRowHidden(unselectablePluginItem->row(), - unselectablePluginItem->parent()->index(), pChecked); + mGui->treeView->setRowHidden(unselectablePluginItem->index(), + unselectablePluginItem->parent()->modelIndex(), pChecked); } // Show/hide our categories, based on whether they contain visible plugins @@ -633,26 +621,26 @@ void PluginsDialog::selectablePluginsCheckBoxToggled(bool pChecked) bool hideCategory = true; - for (int i = 0, iMax = categoryItem->rowCount(); i < iMax; ++i) { - if (!mGui->treeView->isRowHidden(categoryItem->child(i)->row(), - categoryItem->index())) { + for (int i = 0, iMax = categoryItem->childCount(); i < iMax; ++i) { + if (!mGui->treeView->isRowHidden(categoryItem->child(i)->index(), + categoryItem->modelIndex())) { hideCategory = false; break; } } - mGui->treeView->setRowHidden(categoryItem->row(), - mModel->invisibleRootItem()->index(), + mGui->treeView->setRowHidden(categoryItem->index(), + mModel->invisibleRootItem()->modelIndex(), hideCategory); } } // Select the first visible category - for (int i = 0, iMax = mModel->invisibleRootItem()->rowCount(); i < iMax; ++i) { - if (!mGui->treeView->isRowHidden(i, mModel->invisibleRootItem()->index())) { - mGui->treeView->setCurrentIndex(mModel->invisibleRootItem()->child(i)->index()); + for (int i = 0, iMax = mModel->invisibleRootItem()->childCount(); i < iMax; ++i) { + if (!mGui->treeView->isRowHidden(i, mModel->invisibleRootItem()->modelIndex())) { + mGui->treeView->setCurrentIndex(mModel->invisibleRootItem()->child(i)->modelIndex()); return; } diff --git a/src/pluginsdialog.h b/src/pluginsdialog.h index ed667524ca..3a41843d06 100644 --- a/src/pluginsdialog.h +++ b/src/pluginsdialog.h @@ -31,8 +31,6 @@ along with this program. If not, see . //============================================================================== class QSettings; -class QStandardItem; -class QStandardItemModel; //============================================================================== @@ -58,6 +56,8 @@ class PluginItemDelegate : public StyledItemDelegate //============================================================================== class Plugin; +class PluginItem; +class PluginItemModel; class PluginManager; //============================================================================== @@ -75,21 +75,21 @@ class PluginsDialog : public Dialog PluginManager *mPluginManager; - QStandardItemModel *mModel; + PluginItemModel *mModel; - QList mSelectablePluginItems; - QList mUnselectablePluginItems; + QList mSelectablePluginItems; + QList mUnselectablePluginItems; QMap mInitialLoadingStates; - QMap mCategoryItems; - QMap mItemCategories; + QMap mCategoryItems; + QMap mItemCategories; - QStandardItem * pluginCategoryItem(PluginInfo::Category pCategory); + PluginItem * pluginCategoryItem(PluginInfo::Category pCategory); QString statusDescription(Plugin *pPlugin) const; - void updatePluginsSelectedState(QStandardItem *pItem, bool pInitializing); + void updatePluginsSelectedState(PluginItem *pItem, bool pInitializing); private slots: void treeViewCollapsed(const QModelIndex &pIndex); @@ -100,7 +100,7 @@ private slots: void updateInformation(const QModelIndex &pNewIndex, const QModelIndex &pOldIndex); - void updatePluginsSelectedState(QStandardItem *pItem); + void updatePluginsSelectedState(PluginItem *pItem); void openLink(const QString &pLink) const; diff --git a/src/preferencesdialog.cpp b/src/preferencesdialog.cpp index 1f2d2bc7d8..f967a1ed22 100644 --- a/src/preferencesdialog.cpp +++ b/src/preferencesdialog.cpp @@ -24,6 +24,7 @@ along with this program. If not, see . #include "cliutils.h" #include "generalpreferenceswidget.h" #include "guiutils.h" +#include "pluginitemmodel.h" #include "pluginmanager.h" #include "preferencesdialog.h" #include "preferencesinterface.h" @@ -38,7 +39,6 @@ along with this program. If not, see . #include #include #include -#include //============================================================================== @@ -119,7 +119,7 @@ void PreferencesItemDelegate::paint(QPainter *pPainter, // Paint the item as normal, if it is selectable, or bold, if it is a // category - QStandardItem *pluginItem = qobject_cast(pIndex.model())->itemFromIndex(pIndex); + PluginItem *pluginItem = qobject_cast(pIndex.model())->itemFromIndex(pIndex); QStyleOptionViewItem option(pOption); @@ -176,7 +176,7 @@ PreferencesDialog::PreferencesDialog(PluginManager *pPluginManager, // Set up the tree view widget - mModel = new QStandardItemModel(this); + mModel = new PluginItemModel(this); #ifdef Q_OS_MAC mGui->treeView->setAttribute(Qt::WA_MacShowFocusRect, false); @@ -186,10 +186,10 @@ PreferencesDialog::PreferencesDialog(PluginManager *pPluginManager, // Populate the data model with our General section - auto generalPluginItem = new QStandardItem(tr("General")); + auto generalPluginItem = new PluginItem(tr("General")); auto selectedPluginItem = generalPluginItem; - mModel->invisibleRootItem()->appendRow(generalPluginItem); + mModel->invisibleRootItem()->append(generalPluginItem); auto generalPreferencesWidget = new GeneralPreferencesWidget(mainWindow()); @@ -208,9 +208,9 @@ PreferencesDialog::PreferencesDialog(PluginManager *pPluginManager, // Create the item corresponding to the current plugin and add it to // its corresponding category - auto pluginItem = new QStandardItem(plugin->name()); + auto pluginItem = new PluginItem(plugin->name()); - pluginCategoryItem(plugin->info()->category())->appendRow(pluginItem); + pluginCategoryItem(plugin->info()->category())->append(pluginItem); if (plugin->name() == pPluginName) { selectedPluginItem = pluginItem; @@ -258,7 +258,7 @@ PreferencesDialog::PreferencesDialog(PluginManager *pPluginManager, // Select our selected item (!!) - mGui->treeView->setCurrentIndex(selectedPluginItem->index()); + mGui->treeView->setCurrentIndex(selectedPluginItem->modelIndex()); mGui->stackedWidget->currentWidget()->setFocus(); } @@ -283,7 +283,7 @@ QStringList PreferencesDialog::pluginNames() const //============================================================================== -QStandardItem * PreferencesDialog::pluginCategoryItem(PluginInfo::Category pCategory) +PluginItem * PreferencesDialog::pluginCategoryItem(PluginInfo::Category pCategory) { #include "plugincategoryitem.cpp.inl" } @@ -331,7 +331,7 @@ void PreferencesDialog::updatePreferencesWidget(const QModelIndex &pNewIndex, // Check whether we are dealing with a plugin category - QStandardItem *item = mModel->itemFromIndex(pNewIndex); + PluginItem *item = mModel->itemFromIndex(pNewIndex); bool isPluginCategory = std::find(mCategoryItems.begin(), mCategoryItems.end(), item) != mCategoryItems.end(); mResetButton->setEnabled(!isPluginCategory); @@ -340,7 +340,7 @@ void PreferencesDialog::updatePreferencesWidget(const QModelIndex &pNewIndex, // We are dealing with a plugin category, so retrieve and set its name // and description - mPluginCategoryWidget->setCategory(item->text()); + mPluginCategoryWidget->setCategory(item->name()); mPluginCategoryWidget->setDescription(tr("%1.").arg(formatMessage(pluginCategoryDescription(mItemCategories.value(item))))); mGui->stackedWidget->setCurrentWidget(mPluginCategoryWidget); diff --git a/src/preferencesdialog.h b/src/preferencesdialog.h index ae1e77a705..05ea3f9f82 100644 --- a/src/preferencesdialog.h +++ b/src/preferencesdialog.h @@ -32,8 +32,6 @@ along with this program. If not, see . class QLabel; class QSettings; -class QStandardItem; -class QStandardItemModel; //============================================================================== @@ -47,6 +45,8 @@ namespace OpenCOR { //============================================================================== +class PluginItem; +class PluginItemModel; class PluginManager; class PreferencesInterface; @@ -104,11 +104,11 @@ class PreferencesDialog : public Dialog PluginManager *mPluginManager; - QStandardItemModel *mModel; + PluginItemModel *mModel; - QMap mCategoryItems; - QMap mItemCategories; - QMap mItemPreferencesWidgets; + QMap mCategoryItems; + QMap mItemCategories; + QMap mItemPreferencesWidgets; QMap mPreferencesWidgetPluginNames; PreferencesPluginCategoryWidget *mPluginCategoryWidget; @@ -118,7 +118,7 @@ class PreferencesDialog : public Dialog QStringList mPluginNames; - QStandardItem * pluginCategoryItem(PluginInfo::Category pCategory); + PluginItem * pluginCategoryItem(PluginInfo::Category pCategory); private slots: void treeViewCollapsed(const QModelIndex &pIndex);