diff --git a/scwx-qt/source/scwx/qt/model/alert_model.cpp b/scwx-qt/source/scwx/qt/model/alert_model.cpp index 03d3119a..78f693c5 100644 --- a/scwx-qt/source/scwx/qt/model/alert_model.cpp +++ b/scwx-qt/source/scwx/qt/model/alert_model.cpp @@ -310,7 +310,8 @@ void AlertModel::HandleAlert(const types::TextEventKey& alertKey, // Update row if (!p->textEventKeys_.contains(alertKey)) { - beginInsertRows(QModelIndex(), 0, 0); + int newIndex = p->textEventKeys_.size(); + beginInsertRows(QModelIndex(), newIndex, newIndex); p->textEventKeys_.push_back(alertKey); endInsertRows(); } diff --git a/scwx-qt/source/scwx/qt/model/alert_proxy_model.cpp b/scwx-qt/source/scwx/qt/model/alert_proxy_model.cpp index b9f03fea..b91e2cf4 100644 --- a/scwx-qt/source/scwx/qt/model/alert_proxy_model.cpp +++ b/scwx-qt/source/scwx/qt/model/alert_proxy_model.cpp @@ -2,6 +2,12 @@ #include #include #include +#include + +#include +#include + +#include namespace scwx { @@ -16,14 +22,22 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class AlertProxyModelImpl { public: - explicit AlertProxyModelImpl(); - ~AlertProxyModelImpl() = default; + explicit AlertProxyModelImpl(AlertProxyModel* self); + ~AlertProxyModelImpl(); + + void UpdateAlerts(); + + AlertProxyModel* self_; bool alertActiveFilterEnabled_; + + boost::asio::steady_timer alertUpdateTimer_; + std::mutex alertMutex_ {}; }; AlertProxyModel::AlertProxyModel(QObject* parent) : - QSortFilterProxyModel(parent), p(std::make_unique()) + QSortFilterProxyModel(parent), + p(std::make_unique(this)) { } AlertProxyModel::~AlertProxyModel() = default; @@ -63,8 +77,52 @@ bool AlertProxyModel::filterAcceptsRow(int sourceRow, QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); } -AlertProxyModelImpl::AlertProxyModelImpl() : alertActiveFilterEnabled_ {false} +AlertProxyModelImpl::AlertProxyModelImpl(AlertProxyModel* self) : + self_ {self}, + alertActiveFilterEnabled_ {false}, + alertUpdateTimer_ {scwx::util::io_context()} { + // Schedule alert update + UpdateAlerts(); +} + +AlertProxyModelImpl::~AlertProxyModelImpl() +{ + std::unique_lock lock(alertMutex_); + alertUpdateTimer_.cancel(); +} + +void AlertProxyModelImpl::UpdateAlerts() +{ + logger_->trace("UpdateAlerts"); + + // Take a unique lock before modifying feature lists + std::unique_lock lock(alertMutex_); + + // Re-evaluate for expired alerts + if (alertActiveFilterEnabled_) + { + self_->invalidateRowsFilter(); + } + + using namespace std::chrono; + alertUpdateTimer_.expires_after(15s); + alertUpdateTimer_.async_wait( + [=](const boost::system::error_code& e) + { + if (e == boost::asio::error::operation_aborted) + { + logger_->debug("Alert update timer cancelled"); + } + else if (e != boost::system::errc::success) + { + logger_->warn("Alert update timer error: {}", e.message()); + } + else + { + UpdateAlerts(); + } + }); } } // namespace model