123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- /*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
- #include "EditorDefs.h"
- #include "AbstractGroupProxyModel.h"
- AbstractGroupProxyModel::AbstractGroupProxyModel(QObject* parent)
- : QAbstractProxyModel(parent)
- {
- }
- AbstractGroupProxyModel::~AbstractGroupProxyModel()
- {
- }
- QVariant AbstractGroupProxyModel::data(const QModelIndex& index, int role) const
- {
- if (!index.isValid())
- {
- return QVariant();
- }
- const GroupItem* group = reinterpret_cast<GroupItem*>(index.internalPointer());
- if (index.row() >= group->subGroups.count())
- {
- return sourceModel()->data(mapToSource(index), role);
- }
- else if (role == Qt::DisplayRole && index.column() == 0 && !group->subGroups.at(index.row())->groupTitle.isEmpty())
- {
- return group->subGroups[index.row()]->groupTitle;
- }
- else if (group->subGroups.at(index.row())->groupSourceIndex.isValid())
- {
- return group->subGroups.at(index.row())->groupSourceIndex.data(role);
- }
- return QVariant();
- }
- int AbstractGroupProxyModel::rowCount(const QModelIndex& parent) const
- {
- if (!sourceModel())
- {
- return 0;
- }
- // invalid parent - root item is used
- if (!parent.isValid())
- {
- return m_rootItem.subGroups.count() + m_rootItem.sourceIndexes.count();
- }
- // this is the group the parent is in.
- const GroupItem* group = reinterpret_cast<GroupItem*>(parent.internalPointer());
- if (parent.row() < group->subGroups.count())
- {
- return group->subGroups[parent.row()]->subGroups.count() + group->subGroups[parent.row()]->sourceIndexes.count();
- }
- return 0;
- }
- int AbstractGroupProxyModel::columnCount(const QModelIndex& parent) const
- {
- Q_UNUSED(parent)
- if (!sourceModel())
- {
- return 0;
- }
- return sourceModel()->columnCount(QModelIndex());
- }
- QModelIndex AbstractGroupProxyModel::index(int row, int column, const QModelIndex& parent) const
- {
- if (row >= rowCount(parent) || column >= columnCount(parent))
- {
- return QModelIndex();
- }
- if (!parent.isValid())
- {
- return createIndex(row, column, const_cast<GroupItem*>(&m_rootItem));
- }
- const GroupItem* group = reinterpret_cast<GroupItem*>(parent.internalPointer());
- GroupItem* newParent = group->subGroups[parent.row()];
- return createIndex(row, column, newParent);
- }
- QVariant AbstractGroupProxyModel::headerData(int section, Qt::Orientation orientation, int role) const
- {
- return sourceModel()->headerData(section, orientation, role);
- }
- QModelIndex AbstractGroupProxyModel::parent(const QModelIndex& index) const
- {
- GroupItem* group = reinterpret_cast<GroupItem*>(index.internalPointer());
- if (!group)
- {
- return QModelIndex();
- }
- const GroupItem* parentGroup = FindGroup(group);
- if (!parentGroup)
- {
- return QModelIndex();
- }
- const int row = parentGroup->subGroups.indexOf(group);
- return createIndex(row, 0, const_cast<GroupItem*>(parentGroup));
- }
- bool AbstractGroupProxyModel::hasChildren(const QModelIndex& parent) const
- {
- if (!parent.isValid())
- {
- return true;
- }
- const GroupItem* group = reinterpret_cast<GroupItem*>(parent.internalPointer());
- return parent.row() < group->subGroups.count();
- }
- Qt::ItemFlags AbstractGroupProxyModel::flags(const QModelIndex& index) const
- {
- const QModelIndex sourceIndex = mapToSource(index);
- if (!sourceIndex.isValid())
- {
- return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
- }
- return sourceModel()->flags(sourceIndex);
- }
- QModelIndex AbstractGroupProxyModel::mapToSource(const QModelIndex& proxyIndex) const
- {
- GroupItem* group = reinterpret_cast<GroupItem*>(proxyIndex.internalPointer());
- if (!group)
- {
- return QModelIndex();
- }
- const int i = proxyIndex.row() - group->subGroups.count();
- if (i < 0)
- {
- return QModelIndex();
- }
- return group->sourceIndexes[i].sibling(group->sourceIndexes[i].row(), proxyIndex.column());
- }
- QModelIndex AbstractGroupProxyModel::mapFromSource(const QModelIndex& sourceIndex) const
- {
- if (!sourceIndex.isValid())
- {
- return QModelIndex();
- }
-
- GroupItem* group = FindIndex(sourceIndex.sibling(sourceIndex.row(), 0));
- if (!group)
- {
- return QModelIndex();
- }
- if (group->groupSourceIndex == sourceIndex)
- {
- GroupItem* parentGroup = FindGroup(group);
- return createIndex(parentGroup->subGroups.indexOf(group), sourceIndex.column(), parentGroup);
- }
- return createIndex(group->subGroups.count() + group->sourceIndexes.indexOf(sourceIndex.sibling(sourceIndex.row(), 0)),
- sourceIndex.column(), const_cast<GroupItem*>(group));
- }
- AbstractGroupProxyModel::GroupItem* AbstractGroupProxyModel::FindIndex(const QModelIndex& index, GroupItem* group) const
- {
- if (group == nullptr)
- {
- group = const_cast<GroupItem*>(&m_rootItem);
- }
- if (group->sourceIndexes.contains(index) || group->groupSourceIndex == index)
- {
- return group;
- }
- for (GroupItem* subGroup : group->subGroups)
- {
- GroupItem* g = FindIndex(index, subGroup);
- if (g)
- {
- return g;
- }
- }
- return nullptr;
- }
- AbstractGroupProxyModel::GroupItem* AbstractGroupProxyModel::FindGroup(GroupItem* group, GroupItem* parent) const
- {
- if (parent == nullptr)
- {
- parent = const_cast<GroupItem*>(&m_rootItem);
- }
- if (parent->subGroups.contains(group))
- {
- return parent;
- }
- for (GroupItem* subGroup : parent->subGroups)
- {
- GroupItem* g = FindGroup(group, subGroup);
- if (g)
- {
- return g;
- }
- }
- return nullptr;
- }
- void AbstractGroupProxyModel::setSourceModel(QAbstractItemModel* sourceModel)
- {
- QAbstractProxyModel::setSourceModel(sourceModel);
- connect(sourceModel, &QAbstractItemModel::rowsInserted, this, &AbstractGroupProxyModel::SourceRowsInserted);
- connect(sourceModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &AbstractGroupProxyModel::SourceRowsAboutToBeRemoved);
- connect(sourceModel, &QAbstractItemModel::dataChanged, this, &AbstractGroupProxyModel::SourceDataChanged);
- connect(sourceModel, &QAbstractItemModel::modelAboutToBeReset, this, &AbstractGroupProxyModel::slotSourceAboutToBeReset);
- connect(sourceModel, &QAbstractItemModel::modelReset, this, &AbstractGroupProxyModel::slotSourceReset);
- connect(sourceModel, &QAbstractItemModel::layoutAboutToBeChanged, this, &AbstractGroupProxyModel::slotSourceAboutToBeReset);
- connect(sourceModel, &QAbstractItemModel::layoutChanged, this, &AbstractGroupProxyModel::slotSourceReset);
- RebuildTree();
- }
- void AbstractGroupProxyModel::slotSourceAboutToBeReset()
- {
- beginResetModel();
- qDeleteAll(m_rootItem.subGroups);
- m_rootItem.subGroups.clear();
- m_rootItem.sourceIndexes.clear();
- }
- void AbstractGroupProxyModel::slotSourceReset()
- {
- const int rowCount = sourceModel() ? sourceModel()->rowCount() : 0;
- for (int row = 0; row < rowCount; ++row)
- {
- const QModelIndex sourceIndex = sourceModel()->index(row, 0);
- GroupItem* group = CreateGroupIfNotExists(GroupForSourceIndex(sourceIndex));
- if (IsGroupIndex(sourceIndex))
- {
- group->groupSourceIndex = sourceIndex;
- }
- else
- {
- group->sourceIndexes.push_back(sourceIndex);
- }
- }
- endResetModel();
- }
- void AbstractGroupProxyModel::RebuildTree()
- {
- beginResetModel();
- {
- QSignalBlocker blocker(this);
- slotSourceAboutToBeReset();
- slotSourceReset();
- }
- endResetModel();
- Q_EMIT GroupUpdated();
- }
- int AbstractGroupProxyModel::subGroupCount() const
- {
- return m_rootItem.subGroups.count();
- }
- void AbstractGroupProxyModel::SourceRowsInserted(const QModelIndex& p, int from, int to)
- {
- if (p.isValid())
- {
- return;
- }
- for (int row = from; row <= to; ++row)
- {
- const QModelIndex sourceIndex = sourceModel()->index(row, 0);
- GroupItem* group = CreateGroupIfNotExists(GroupForSourceIndex(sourceIndex));
- if (IsGroupIndex(sourceIndex))
- {
- group->groupSourceIndex = sourceIndex;
- }
- else
- {
- const int modelRow = group->subGroups.count() + group->sourceIndexes.count();
- beginInsertRows(parent(createIndex(0, 0, group)), modelRow, modelRow);
- group->sourceIndexes.push_back(sourceIndex);
- endInsertRows();
- }
- }
- Q_EMIT GroupUpdated();
- }
- void AbstractGroupProxyModel::SourceRowsAboutToBeRemoved(const QModelIndex& p, int from, int to)
- {
- if (p.isValid())
- {
- return;
- }
- for (int row = from; row <= to; ++row)
- {
- const QModelIndex sourceIndex = sourceModel()->index(row, 0);
- GroupItem* group = const_cast<GroupItem*>(FindIndex(sourceIndex));
- if (!group)
- {
- continue;
- }
- if (group->groupSourceIndex != sourceIndex)
- {
- const int modelRow = group->subGroups.count() + group->sourceIndexes.indexOf(sourceIndex);
- beginRemoveRows(parent(createIndex(0, 0, group)), modelRow, modelRow);
- group->sourceIndexes.remove(group->sourceIndexes.indexOf(sourceIndex));
- endRemoveRows();
- }
- RemoveEmptyGroup(group);
- }
- Q_EMIT GroupUpdated();
- }
- void AbstractGroupProxyModel::SourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
- {
- if (topLeft.parent().isValid())
- {
- return;
- }
- for (int row = topLeft.row(); row <= bottomRight.row(); ++row)
- {
- const QModelIndex sourceIndex = sourceModel()->index(row, 0);
- const GroupItem* currentGroup = FindIndex(sourceIndex);
- GroupItem* newGroup = CreateGroupIfNotExists(GroupForSourceIndex(sourceIndex));
- if (currentGroup != newGroup)
- {
- SourceRowsAboutToBeRemoved(QModelIndex(), row, row);
- SourceRowsInserted(QModelIndex(), row, row);
- }
- else
- {
- emit dataChanged(mapFromSource(sourceIndex), mapFromSource(sourceIndex.sibling(row, columnCount() - 1)));
- }
- }
- Q_EMIT GroupUpdated();
- }
- AbstractGroupProxyModel::GroupItem* AbstractGroupProxyModel::CreateGroupIfNotExists(QStringList group)
- {
- GroupItem* currentGroup = &m_rootItem;
- while (true)
- {
- if (group.isEmpty())
- {
- return currentGroup;
- }
- auto matchingSubGroup = std::find_if(currentGroup->subGroups.begin(), currentGroup->subGroups.end(),
- [=](const GroupItem* g)
- {
- return QString::compare(g->groupTitle, group.first(), Qt::CaseInsensitive) == 0;
- }
- );
- if (matchingSubGroup == currentGroup->subGroups.end())
- {
- GroupItem* newGroup = new GroupItem;
- newGroup->groupTitle = group.first();
- beginInsertRows(parent(createIndex(0, 0, currentGroup)),
- currentGroup->subGroups.size(), currentGroup->subGroups.size());
- currentGroup->subGroups.push_back(newGroup);
- endInsertRows();
- currentGroup = currentGroup->subGroups[currentGroup->subGroups.size() - 1];
- }
- else
- {
- currentGroup = *matchingSubGroup;
- }
- group.pop_front();
- }
- }
- void AbstractGroupProxyModel::RemoveEmptyGroup(GroupItem* group)
- {
- if (!group->subGroups.isEmpty() || !group->sourceIndexes.isEmpty() || group == &m_rootItem
- || (group->groupSourceIndex.isValid() && !IsGroupIndex(group->groupSourceIndex)))
- {
- return;
- }
- GroupItem* parentGroup = const_cast<GroupItem*>(FindGroup(group));
- const int row = parentGroup->subGroups.indexOf(group);
- beginRemoveRows(parent(createIndex(0, 0, parentGroup)), row, row);
- delete parentGroup->subGroups.takeAt(row);
- endRemoveRows();
- RemoveEmptyGroup(parentGroup);
- }
- #include <Util/moc_AbstractGroupProxyModel.cpp>
|