Skip to content

Commit

Permalink
Plugins and preferences dialog: improved our use of tree views.
Browse files Browse the repository at this point in the history
This is part of our work on issue #2285.
  • Loading branch information
agarny committed Feb 12, 2020
1 parent 5215a38 commit 7dce10c
Show file tree
Hide file tree
Showing 8 changed files with 511 additions and 82 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Expand Up @@ -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
Expand Down
14 changes: 7 additions & 7 deletions 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
Expand Down
322 changes: 322 additions & 0 deletions 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 <https://gnu.org/licenses>.
*******************************************************************************/

//==============================================================================
// 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<PluginItem *>(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<PluginItem*>(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<PluginItem *>(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<PluginItem *>(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<PluginItem *>(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<PluginItem *>(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
//==============================================================================

0 comments on commit 7dce10c

Please sign in to comment.