diff --git a/apps/opencs/model/filter/parser.cpp b/apps/opencs/model/filter/parser.cpp index aadad5f8f5..6248b03bb4 100644 --- a/apps/opencs/model/filter/parser.cpp +++ b/apps/opencs/model/filter/parser.cpp @@ -452,7 +452,10 @@ std::shared_ptr CSMFilter::Parser::parseText() return std::shared_ptr(); } - return std::make_shared(columnId, text); + auto node = std::make_shared(columnId, text); + if (!node->isValid()) + error(); + return node; } std::shared_ptr CSMFilter::Parser::parseValue() diff --git a/apps/opencs/model/filter/textnode.hpp b/apps/opencs/model/filter/textnode.hpp index 14efa0a3a0..d629cbe336 100644 --- a/apps/opencs/model/filter/textnode.hpp +++ b/apps/opencs/model/filter/textnode.hpp @@ -34,6 +34,8 @@ namespace CSMFilter ///< Return a string that represents this node. /// /// \param numericColumns Use numeric IDs instead of string to represent columns. + + bool isValid() { return mRegExp.isValid(); } }; } diff --git a/apps/opencs/model/prefs/state.cpp b/apps/opencs/model/prefs/state.cpp index c11996a6ea..ba3a544f36 100644 --- a/apps/opencs/model/prefs/state.cpp +++ b/apps/opencs/model/prefs/state.cpp @@ -90,6 +90,7 @@ void CSMPrefs::State::declare() .setTooltip( "When editing a record, open the view in a new window," " rather than docked in the main view."); + declareInt(mValues->mIdTables.mFilterDelay, "Delay before applying a filter (in miliseconds)"); declareCategory("ID Dialogues"); declareBool(mValues->mIdDialogues.mToolbar, "Show toolbar"); diff --git a/apps/opencs/model/prefs/values.hpp b/apps/opencs/model/prefs/values.hpp index 9899a239a9..d3f78e5d01 100644 --- a/apps/opencs/model/prefs/values.hpp +++ b/apps/opencs/model/prefs/values.hpp @@ -138,6 +138,7 @@ namespace CSMPrefs EnumSettingValue mJumpToAdded{ mIndex, sName, "jump-to-added", sJumpAndSelectValues, 0 }; Settings::SettingValue mExtendedConfig{ mIndex, sName, "extended-config", false }; Settings::SettingValue mSubviewNewWindow{ mIndex, sName, "subview-new-window", false }; + Settings::SettingValue mFilterDelay{ mIndex, sName, "filter-delay", 500 }; }; struct IdDialoguesCategory : Settings::WithIndex diff --git a/apps/opencs/model/world/idtableproxymodel.cpp b/apps/opencs/model/world/idtableproxymodel.cpp index d4e342f5de..c03b4ea30a 100644 --- a/apps/opencs/model/world/idtableproxymodel.cpp +++ b/apps/opencs/model/world/idtableproxymodel.cpp @@ -63,9 +63,18 @@ bool CSMWorld::IdTableProxyModel::filterAcceptsRow(int sourceRow, const QModelIn CSMWorld::IdTableProxyModel::IdTableProxyModel(QObject* parent) : QSortFilterProxyModel(parent) + , mFilterTimer{ new QTimer(this) } , 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.get(), &QTimer::timeout, this, [this]() { this->timerTimeout(); }); } QModelIndex CSMWorld::IdTableProxyModel::getModelIndex(const std::string& id, int column) const @@ -87,10 +96,8 @@ void CSMWorld::IdTableProxyModel::setSourceModel(QAbstractItemModel* model) void CSMWorld::IdTableProxyModel::setFilter(const std::shared_ptr& filter) { - beginResetModel(); - mFilter = filter; - updateColumnMap(); - endResetModel(); + mAwaitingFilter = filter; + mFilterTimer->start(); } bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex& left, const QModelIndex& right) const @@ -131,6 +138,26 @@ void CSMWorld::IdTableProxyModel::refreshFilter() } } +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) { refreshFilter(); diff --git a/apps/opencs/model/world/idtableproxymodel.hpp b/apps/opencs/model/world/idtableproxymodel.hpp index 639cf47287..b7d38f5a2d 100644 --- a/apps/opencs/model/world/idtableproxymodel.hpp +++ b/apps/opencs/model/world/idtableproxymodel.hpp @@ -10,6 +10,9 @@ #include #include #include +#include + +#include "../prefs/state.hpp" #include "columns.hpp" @@ -29,6 +32,8 @@ namespace CSMWorld Q_OBJECT std::shared_ptr mFilter; + std::unique_ptr mFilterTimer; + std::shared_ptr mAwaitingFilter; std::map mColumnMap; // column ID, column index in this model (or -1) // Cache of enum values for enum columns (e.g. Modified, Record Type). @@ -68,6 +73,10 @@ namespace CSMWorld virtual void sourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); + void timerTimeout(); + + void settingChanged(const CSMPrefs::Setting* setting); + signals: void rowAdded(const std::string& id);