From 0ddd9d91eaa59ddd76f0cb62644dc9894a0a8e60 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Fri, 26 May 2023 16:14:33 -0500 Subject: [PATCH] Timeline step back --- .../scwx/qt/manager/timeline_manager.cpp | 63 +++++++++++++++++++ wxdata/include/scwx/util/map.hpp | 39 ++++++++---- 2 files changed, 90 insertions(+), 12 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp b/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp index 7269aee1..4d25f09b 100644 --- a/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/timeline_manager.cpp @@ -33,6 +33,7 @@ public: TimelineManager* self_; void SelectTime(std::chrono::system_clock::time_point selectedTime = {}); + void StepBack(); std::string radarSite_ {"?"}; std::string previousRadarSite_ {"?"}; @@ -51,6 +52,12 @@ TimelineManager::~TimelineManager() = default; void TimelineManager::SetRadarSite(const std::string& radarSite) { + if (p->radarSite_ == radarSite) + { + // No action needed + return; + } + logger_->debug("SetRadarSite: {}", radarSite); p->radarSite_ = radarSite; @@ -123,6 +130,8 @@ void TimelineManager::AnimationStepBegin() void TimelineManager::AnimationStepBack() { logger_->debug("AnimationStepBack"); + + p->StepBack(); } void TimelineManager::AnimationPlay() @@ -217,6 +226,60 @@ void TimelineManager::Impl::SelectTime( }); } +void TimelineManager::Impl::StepBack() +{ + scwx::util::async( + [this]() + { + // Take a lock for time selection + std::unique_lock lock {selectTimeMutex_}; + + // Determine time to get active volume times + std::chrono::system_clock::time_point queryTime = adjustedTime_; + if (queryTime == std::chrono::system_clock::time_point {}) + { + queryTime = std::chrono::system_clock::now(); + } + + // Request active volume times + auto radarProductManager = + manager::RadarProductManager::Instance(radarSite_); + auto volumeTimes = + radarProductManager->GetActiveVolumeTimes(queryTime); + + std::set::const_iterator it; + + if (adjustedTime_ == std::chrono::system_clock::time_point {}) + { + // If the adjusted time is live, get the last element in the set + it = volumeTimes.cend(); + if (!volumeTimes.empty()) + { + --it; + } + } + else + { + // Get the current element in the set + it = scwx::util::GetBoundedElementIterator(volumeTimes, + adjustedTime_); + } + + // Only if we aren't at the beginning of the volume times set + if (it != volumeTimes.cbegin()) + { + // Select the previous time + adjustedTime_ = *(--it); + selectedTime_ = adjustedTime_; + + logger_->debug("Volume time updated: {}", + scwx::util::TimeString(adjustedTime_)); + + emit self_->VolumeTimeUpdated(adjustedTime_); + } + }); +} + std::shared_ptr TimelineManager::Instance() { static std::weak_ptr timelineManagerReference_ {}; diff --git a/wxdata/include/scwx/util/map.hpp b/wxdata/include/scwx/util/map.hpp index b6282807..f35e2abf 100644 --- a/wxdata/include/scwx/util/map.hpp +++ b/wxdata/include/scwx/util/map.hpp @@ -8,14 +8,13 @@ namespace scwx namespace util { -template -ReturnType GetBoundedElementPointer(Container& container, - const typename Container::key_type& key) +template +Container::const_iterator +GetBoundedElementIterator(Container& container, + const typename Container::key_type& key) { - ReturnType elementPtr {nullptr}; - // Find the first element greater than the key requested - auto it = container.upper_bound(key); + typename Container::const_iterator it = container.upper_bound(key); // An element with a key greater was found if (it != container.cend()) @@ -25,19 +24,34 @@ ReturnType GetBoundedElementPointer(Container& container, { // Get the element immediately preceding, this the element we are // looking for - elementPtr = &(*(--it)); + --it; } else { // The current element is a good substitute - elementPtr = &(*it); } } else if (container.size() > 0) { // An element with a key greater was not found. If it exists, it must be - // the last element. - elementPtr = &(*container.rbegin()); + // the last element. Decrement the end iterator. + --it; + } + + return it; +} + +template +ReturnType GetBoundedElementPointer(Container& container, + const typename Container::key_type& key) +{ + ReturnType elementPtr {nullptr}; + + auto it = GetBoundedElementIterator(container, key); + + if (it != container.cend()) + { + elementPtr = &(*(it)); } return elementPtr; @@ -48,9 +62,10 @@ ReturnType GetBoundedElement(std::map& map, const Key& key) { ReturnType element; - typename std::map::pointer elementPtr = + typename std::map::const_pointer elementPtr = GetBoundedElementPointer, - typename std::map::pointer>(map, key); + typename std::map::const_pointer>(map, + key); if (elementPtr != nullptr) { element = elementPtr->second;