Handle removed alerts from alert layer

This commit is contained in:
Dan Paulat 2025-05-04 23:05:21 -05:00
parent f37a77a9f7
commit 671ec1d658

View file

@ -73,10 +73,11 @@ public:
connect(textEventManager_.get(), connect(textEventManager_.get(),
&manager::TextEventManager::AlertUpdated, &manager::TextEventManager::AlertUpdated,
this, this,
[this](const types::TextEventKey& key, &AlertLayerHandler::HandleAlert);
std::size_t messageIndex, connect(textEventManager_.get(),
boost::uuids::uuid uuid) &manager::TextEventManager::AlertsRemoved,
{ HandleAlert(key, messageIndex, uuid); }); this,
&AlertLayerHandler::HandleAlertsRemoved);
} }
~AlertLayerHandler() ~AlertLayerHandler()
{ {
@ -100,6 +101,10 @@ public:
void HandleAlert(const types::TextEventKey& key, void HandleAlert(const types::TextEventKey& key,
size_t messageIndex, size_t messageIndex,
boost::uuids::uuid uuid); boost::uuids::uuid uuid);
void HandleAlertsRemoved(
const std::unordered_set<types::TextEventKey,
types::TextEventHash<types::TextEventKey>>&
keys);
static AlertLayerHandler& Instance(); static AlertLayerHandler& Instance();
@ -112,6 +117,7 @@ signals:
void AlertAdded(const std::shared_ptr<SegmentRecord>& segmentRecord, void AlertAdded(const std::shared_ptr<SegmentRecord>& segmentRecord,
awips::Phenomenon phenomenon); awips::Phenomenon phenomenon);
void AlertUpdated(const std::shared_ptr<SegmentRecord>& segmentRecord); void AlertUpdated(const std::shared_ptr<SegmentRecord>& segmentRecord);
void AlertsRemoved(awips::Phenomenon phenomenon, bool alertActive);
void AlertsUpdated(awips::Phenomenon phenomenon, bool alertActive); void AlertsUpdated(awips::Phenomenon phenomenon, bool alertActive);
}; };
@ -190,6 +196,7 @@ public:
bool enableHover, bool enableHover,
boost::container::stable_vector< boost::container::stable_vector<
std::shared_ptr<gl::draw::GeoLineDrawItem>>& drawItems); std::shared_ptr<gl::draw::GeoLineDrawItem>>& drawItems);
void PopulateLines(bool alertActive);
void UpdateLines(); void UpdateLines();
static LineData CreateLineData(const settings::LineSettings& lineSettings); static LineData CreateLineData(const settings::LineSettings& lineSettings);
@ -276,22 +283,7 @@ void AlertLayer::Initialize()
for (auto alertActive : {false, true}) for (auto alertActive : {false, true})
{ {
auto& geoLines = p->geoLines_.at(alertActive); p->PopulateLines(alertActive);
geoLines->StartLines();
// Populate initial segments
auto segmentsIt =
alertLayerHandler.segmentsByType_.find({p->phenomenon_, alertActive});
if (segmentsIt != alertLayerHandler.segmentsByType_.cend())
{
for (auto& segment : segmentsIt->second)
{
p->AddAlert(segment);
}
}
geoLines->FinishLines();
} }
p->ConnectAlertHandlerSignals(); p->ConnectAlertHandlerSignals();
@ -444,6 +436,65 @@ void AlertLayerHandler::HandleAlert(const types::TextEventKey& key,
} }
} }
void AlertLayerHandler::HandleAlertsRemoved(
const std::unordered_set<types::TextEventKey,
types::TextEventHash<types::TextEventKey>>& keys)
{
logger_->trace("HandleAlertsRemoved: {} keys", keys.size());
std::unordered_set<std::pair<awips::Phenomenon, bool>,
AlertTypeHash<std::pair<awips::Phenomenon, bool>>>
alertsRemoved {};
// Take a unique lock before modifying segments
std::unique_lock lock {alertMutex_};
for (const auto& key : keys)
{
// Remove segments associated with the key
auto segmentsIt = segmentsByKey_.find(key);
if (segmentsIt != segmentsByKey_.end())
{
for (const auto& segmentRecord : segmentsIt->second)
{
auto& segment = segmentRecord->segment_;
bool alertActive = IsAlertActive(segment);
// Remove from segmentsByType_
auto typeIt = segmentsByType_.find({key.phenomenon_, alertActive});
if (typeIt != segmentsByType_.end())
{
auto& segmentsForType = typeIt->second;
segmentsForType.erase(std::remove(segmentsForType.begin(),
segmentsForType.end(),
segmentRecord),
segmentsForType.end());
// If no segments remain for this type, erase the entry
if (segmentsForType.empty())
{
segmentsByType_.erase(typeIt);
}
}
alertsRemoved.emplace(key.phenomenon_, alertActive);
}
// Remove the key from segmentsByKey_
segmentsByKey_.erase(segmentsIt);
}
}
// Release the lock after completing segment updates
lock.unlock();
// Emit signal to notify that alerts have been removed
for (auto& alert : alertsRemoved)
{
Q_EMIT AlertsRemoved(alert.first, alert.second);
}
}
void AlertLayer::Impl::ConnectAlertHandlerSignals() void AlertLayer::Impl::ConnectAlertHandlerSignals()
{ {
auto& alertLayerHandler = AlertLayerHandler::Instance(); auto& alertLayerHandler = AlertLayerHandler::Instance();
@ -473,6 +524,22 @@ void AlertLayer::Impl::ConnectAlertHandlerSignals()
UpdateAlert(segmentRecord); UpdateAlert(segmentRecord);
} }
}); });
QObject::connect(
&alertLayerHandler,
&AlertLayerHandler::AlertsRemoved,
receiver_.get(),
[&alertLayerHandler, this](awips::Phenomenon phenomenon, bool alertActive)
{
if (phenomenon == phenomenon_)
{
// Take a shared lock to prevent handling additional alerts while
// populating initial lists
const std::shared_lock lock {alertLayerHandler.alertMutex_};
// Re-populate the lines if multiple alerts were removed
PopulateLines(alertActive);
}
});
} }
void AlertLayer::Impl::ConnectSignals() void AlertLayer::Impl::ConnectSignals()
@ -704,6 +771,27 @@ void AlertLayer::Impl::AddLine(std::shared_ptr<gl::draw::GeoLines>& geoLines,
} }
} }
void AlertLayer::Impl::PopulateLines(bool alertActive)
{
auto& alertLayerHandler = AlertLayerHandler::Instance();
auto& geoLines = geoLines_.at(alertActive);
geoLines->StartLines();
// Populate initial segments
auto segmentsIt =
alertLayerHandler.segmentsByType_.find({phenomenon_, alertActive});
if (segmentsIt != alertLayerHandler.segmentsByType_.cend())
{
for (auto& segment : segmentsIt->second)
{
AddAlert(segment);
}
}
geoLines->FinishLines();
}
void AlertLayer::Impl::UpdateLines() void AlertLayer::Impl::UpdateLines()
{ {
std::unique_lock lock {linesMutex_}; std::unique_lock lock {linesMutex_};