openblocks/editor/explorermodel.cpp

116 lines
3.9 KiB
C++
Raw Normal View History

2025-01-17 23:13:42 +00:00
#include "explorermodel.h"
#include "objects/base/instance.h"
#include "qcontainerfwd.h"
#include "qobject.h"
#include "qwidget.h"
2025-01-18 15:27:43 +00:00
#include "common.h"
#include <algorithm>
#include <optional>
2025-01-17 23:13:42 +00:00
// https://doc.qt.io/qt-6/qtwidgets-itemviews-simpletreemodel-example.html#testing-the-model
ExplorerModel::ExplorerModel(InstanceRef dataRoot, QWidget *parent)
: QAbstractItemModel(parent)
, rootItem(dataRoot) {
2025-01-18 15:27:43 +00:00
// TODO: Don't use lambdas and handlers like that
hierarchyPreUpdateHandler = [&](InstanceRef object, std::optional<InstanceRef> oldParent, std::optional<InstanceRef> newParent) {
if (oldParent.has_value()) {
auto children = oldParent.value()->GetChildren();
size_t idx = std::find(children.begin(), children.end(), object) - children.end();
beginRemoveRows(toIndex(oldParent.value()), idx, idx);
}
if (newParent.has_value()) {
size_t size = newParent.value()->GetChildren().size();
beginInsertRows(toIndex(newParent.value()), size, size);
} else {
// TODO:
}
};
hierarchyPostUpdateHandler = [&](InstanceRef object, std::optional<InstanceRef> oldParent, std::optional<InstanceRef> newParent) {
if (newParent.has_value()) endInsertRows();
if (oldParent.has_value()) endRemoveRows();
};
2025-01-17 23:13:42 +00:00
}
ExplorerModel::~ExplorerModel() = default;
QModelIndex ExplorerModel::index(int row, int column, const QModelIndex &parent) const {
if (!hasIndex(row, column, parent))
return {};
Instance* parentItem = parent.isValid()
? static_cast<Instance*>(parent.internalPointer())
: rootItem.get();
if (parentItem->GetChildren().size() >= row)
return createIndex(row, column, parentItem->GetChildren()[row].get());
return {};
}
2025-01-18 15:27:43 +00:00
QModelIndex ExplorerModel::toIndex(InstanceRef item) {
if (item == rootItem)
return {};
InstanceRef parentItem = item->GetParent().value();
// Check above ensures this item is not root, so value() must be valid
for (int i = 0; i < parentItem->GetChildren().size(); i++)
if (parentItem->GetChildren()[i] == item)
return createIndex(i, 0, item.get());
return QModelIndex{};
}
2025-01-17 23:13:42 +00:00
QModelIndex ExplorerModel::parent(const QModelIndex &index) const {
if (!index.isValid())
return {};
Instance* childItem = static_cast<Instance*>(index.internalPointer());
// NORISK: The parent must exist if the child was obtained from it during this frame
InstanceRef parentItem = childItem->GetParent().value();
if (parentItem == rootItem)
return {};
// Check above ensures this item is not root, so value() must be valid
InstanceRef parentParent = parentItem->GetParent().value();
for (int i = 0; i < parentParent->GetChildren().size(); i++)
if (parentParent->GetChildren()[i] == parentItem)
return createIndex(i, 0, parentItem.get());
return QModelIndex{};
}
int ExplorerModel::rowCount(const QModelIndex &parent) const {
if (parent.column() > 0)
return 0;
Instance* parentItem = parent.isValid()
? static_cast<Instance*>(parent.internalPointer())
: rootItem.get();
return parentItem->GetChildren().size();
}
int ExplorerModel::columnCount(const QModelIndex &parent) const {
return 1;
}
QVariant ExplorerModel::data(const QModelIndex &index, int role) const {
if (!index.isValid() || role != Qt::DisplayRole)
return {};
const Instance *item = static_cast<const Instance*>(index.internalPointer());
return QString::fromStdString(item->name);
}
QVariant ExplorerModel::headerData(int section, Qt::Orientation orientation,
int role) const
{
return QString("Idk lol \u00AF\u005C\u005F\u0028\u30C4\u0029\u005F\u002F\u00AF");
}
Qt::ItemFlags ExplorerModel::flags(const QModelIndex &index) const
{
return index.isValid()
? QAbstractItemModel::flags(index) : Qt::ItemFlags(Qt::NoItemFlags);
}