Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165#include "idtableproxymodel.hpp"
#include <QAbstractItemModel>#include <QModelIndex>#include <QSortFilterProxyModel>#include <QString>
#include <compare>#include <string_view>#include <type_traits>#include <vector>
#include <apps/opencs/model/filter/node.hpp>#include <apps/opencs/model/world/columns.hpp>
#include "columnbase.hpp"#include "idtablebase.hpp"
class QObject;
namespace{ std::string_view getEnumValue(const std::vector<std::pair<int, std::string>>& values, int index) { if (index < 0 || index >= static_cast<int>(values.size())) { return {}; } return values[index].second; }}
void CSMWorld::IdTableProxyModel::updateColumnMap(){ Q_ASSERT(mSourceModel != nullptr);
mColumnMap.clear(); if (mFilter) { std::vector<int> columns = mFilter->getReferencedColumns(); for (std::vector<int>::const_iterator iter(columns.begin()); iter != columns.end(); ++iter) mColumnMap.insert(std::make_pair( *iter, mSourceModel->searchColumnIndex(static_cast<CSMWorld::Columns::ColumnId>(*iter)))); }}
bool CSMWorld::IdTableProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const{ Q_ASSERT(mSourceModel != nullptr);
// It is not possible to use filterAcceptsColumn() and check for // sourceModel()->headerData (sourceColumn, Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags) // because the sourceColumn parameter excludes the hidden columns, i.e. wrong columns can // be rejected. Workaround by disallowing tree branches (nested columns), which are not meant // to be visible, from the filter. if (sourceParent.isValid()) return false;
if (!mFilter) return true;
return mFilter->test(*mSourceModel, sourceRow, mColumnMap);}
CSMWorld::IdTableProxyModel::IdTableProxyModel(QObject* parent) : QSortFilterProxyModel(parent) , mSourceModel(nullptr){ setSortCaseSensitivity(Qt::CaseInsensitive);
mFilterTimer.setSingleShot(true); int intervalSetting = CSMPrefs::State::get()["ID Tables"]["filter-delay"].toInt(); mFilterTimer.setInterval(intervalSetting);
connect(&CSMPrefs::State::get(), &CSMPrefs::State::settingChanged, this, [this](const CSMPrefs::Setting* setting) { this->settingChanged(setting); }); connect(&mFilterTimer, &QTimer::timeout, this, [this]() { this->timerTimeout(); });}
QModelIndex CSMWorld::IdTableProxyModel::getModelIndex(const std::string& id, int column) const{ Q_ASSERT(mSourceModel != nullptr);
return mapFromSource(mSourceModel->getModelIndex(id, column));}
void CSMWorld::IdTableProxyModel::setSourceModel(QAbstractItemModel* model){ QSortFilterProxyModel::setSourceModel(model);
mSourceModel = dynamic_cast<IdTableBase*>(sourceModel()); connect(mSourceModel, &IdTableBase::rowsInserted, this, &IdTableProxyModel::sourceRowsInserted); connect(mSourceModel, &IdTableBase::rowsRemoved, this, &IdTableProxyModel::sourceRowsRemoved); connect(mSourceModel, &IdTableBase::dataChanged, this, &IdTableProxyModel::sourceDataChanged);}
void CSMWorld::IdTableProxyModel::setFilter(const std::shared_ptr<CSMFilter::Node>& filter){ mAwaitingFilter = filter; mFilterTimer.start();}
bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const{ Columns::ColumnId id = static_cast<Columns::ColumnId>(left.data(ColumnBase::Role_ColumnId).toInt()); EnumColumnCache::const_iterator valuesIt = mEnumColumnCache.find(id); if (valuesIt == mEnumColumnCache.end()) { if (Columns::hasEnums(id)) { valuesIt = mEnumColumnCache.insert(std::make_pair(id, Columns::getEnums(id))).first; } }
if (valuesIt != mEnumColumnCache.end()) { std::string_view first = getEnumValue(valuesIt->second, left.data().toInt()); std::string_view second = getEnumValue(valuesIt->second, right.data().toInt()); return first < second; } return QSortFilterProxyModel::lessThan(left, right);}
QString CSMWorld::IdTableProxyModel::getRecordId(int sourceRow) const{ Q_ASSERT(mSourceModel != nullptr);
int idColumn = mSourceModel->findColumnIndex(Columns::ColumnId_Id); return mSourceModel->data(mSourceModel->index(sourceRow, idColumn)).toString();}
void CSMWorld::IdTableProxyModel::timerTimeout(){ if (mAwaitingFilter) { beginResetModel(); mFilter = mAwaitingFilter; updateColumnMap(); endResetModel(); mAwaitingFilter.reset(); }}
void CSMWorld::IdTableProxyModel::settingChanged(const CSMPrefs::Setting* setting){ if (*setting == "ID Tables/filter-delay") { mFilterTimer.setInterval(setting->toInt()); }}
void CSMWorld::IdTableProxyModel::sourceRowsInserted(const QModelIndex& parent, int /*start*/, int end){ if (!parent.isValid()) { emit rowAdded(getRecordId(end).toUtf8().constData()); }}
void CSMWorld::IdTableProxyModel::sourceRowsRemoved(const QModelIndex& /*parent*/, int /*start*/, int /*end*/) {}
void CSMWorld::IdTableProxyModel::sourceDataChanged(const QModelIndex& /*topLeft*/, const QModelIndex& /*bottomRight*/){}