mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 14:20:05 +00:00
Merge pull request #466 from AdenKoperczak/timezone-for-timeline
Make animation dock follow default timezones
This commit is contained in:
commit
58b6c5e1eb
8 changed files with 194 additions and 37 deletions
|
|
@ -141,6 +141,7 @@ public:
|
|||
~MainWindowImpl()
|
||||
{
|
||||
homeRadarConnection_.disconnect();
|
||||
defaultTimeZoneConnection_.disconnect();
|
||||
|
||||
auto& generalSettings = settings::GeneralSettings::Instance();
|
||||
|
||||
|
|
@ -245,6 +246,7 @@ public:
|
|||
bool layerActionsInitialized_ {false};
|
||||
|
||||
boost::signals2::scoped_connection homeRadarConnection_ {};
|
||||
boost::signals2::scoped_connection defaultTimeZoneConnection_ {};
|
||||
|
||||
std::vector<map::MapWidget*> maps_;
|
||||
|
||||
|
|
@ -377,6 +379,7 @@ MainWindow::MainWindow(QWidget* parent) :
|
|||
p->animationDockWidget_ = new ui::AnimationDockWidget(this);
|
||||
p->timelineGroup_->GetContentsLayout()->addWidget(p->animationDockWidget_);
|
||||
ui->radarToolboxScrollAreaContents->layout()->addWidget(p->timelineGroup_);
|
||||
p->animationDockWidget_->UpdateTimeZone(p->activeMap_->GetDefaultTimeZone());
|
||||
|
||||
// Reset toolbox spacer at the bottom
|
||||
ui->radarToolboxScrollAreaContents->layout()->removeItem(
|
||||
|
|
@ -982,6 +985,16 @@ void MainWindowImpl::ConnectMapSignals()
|
|||
|
||||
void MainWindowImpl::ConnectAnimationSignals()
|
||||
{
|
||||
defaultTimeZoneConnection_ = settings::GeneralSettings::Instance()
|
||||
.default_time_zone()
|
||||
.changed_signal()
|
||||
.connect(
|
||||
[this]()
|
||||
{
|
||||
animationDockWidget_->UpdateTimeZone(
|
||||
activeMap_->GetDefaultTimeZone());
|
||||
});
|
||||
|
||||
connect(animationDockWidget_,
|
||||
&ui::AnimationDockWidget::DateTimeChanged,
|
||||
timelineManager_.get(),
|
||||
|
|
@ -1602,6 +1615,8 @@ void MainWindowImpl::UpdateRadarSite()
|
|||
|
||||
alertManager_->SetRadarSite(radarSite);
|
||||
placefileManager_->SetRadarSite(radarSite);
|
||||
|
||||
animationDockWidget_->UpdateTimeZone(activeMap_->GetDefaultTimeZone());
|
||||
}
|
||||
|
||||
void MainWindowImpl::UpdateVcp()
|
||||
|
|
|
|||
|
|
@ -821,6 +821,11 @@ void MapWidget::SetSmoothingEnabled(bool smoothingEnabled)
|
|||
}
|
||||
}
|
||||
|
||||
const scwx::util::time_zone* MapWidget::GetDefaultTimeZone() const
|
||||
{
|
||||
return p->radarProductManager_->default_time_zone();
|
||||
}
|
||||
|
||||
void MapWidget::SelectElevation(float elevation)
|
||||
{
|
||||
auto radarProductView = p->context_->radar_product_view();
|
||||
|
|
|
|||
|
|
@ -45,9 +45,10 @@ public:
|
|||
void DumpLayerList() const;
|
||||
|
||||
[[nodiscard]] common::Level3ProductCategoryMap
|
||||
GetAvailableLevel3Categories();
|
||||
[[nodiscard]] std::optional<float> GetElevation() const;
|
||||
[[nodiscard]] std::vector<float> GetElevationCuts() const;
|
||||
GetAvailableLevel3Categories();
|
||||
[[nodiscard]] const scwx::util::time_zone* GetDefaultTimeZone() const;
|
||||
[[nodiscard]] std::optional<float> GetElevation() const;
|
||||
[[nodiscard]] std::vector<float> GetElevationCuts() const;
|
||||
[[nodiscard]] std::optional<float> GetIncomingLevel2Elevation() const;
|
||||
[[nodiscard]] std::vector<std::string> GetLevel3Products();
|
||||
[[nodiscard]] std::string GetMapStyle() const;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,14 @@ namespace ui
|
|||
static const std::string logPrefix_ = "scwx::qt::ui::animation_dock_widget";
|
||||
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
|
||||
|
||||
#if (__cpp_lib_chrono >= 201907L)
|
||||
using local_days = std::chrono::local_days;
|
||||
using zoned_time_ = std::chrono::zoned_time<std::chrono::seconds>;
|
||||
#else
|
||||
using local_days = date::local_days;
|
||||
using zoned_time_ = date::zoned_time<std::chrono::seconds>;
|
||||
#endif
|
||||
|
||||
class AnimationDockWidgetImpl
|
||||
{
|
||||
public:
|
||||
|
|
@ -47,8 +55,14 @@ public:
|
|||
types::MapTime viewType_ {types::MapTime::Live};
|
||||
bool isLive_ {true};
|
||||
|
||||
std::chrono::sys_days selectedDate_ {};
|
||||
std::chrono::seconds selectedTime_ {};
|
||||
local_days selectedDate_ {};
|
||||
std::chrono::seconds selectedTime_ {};
|
||||
|
||||
const scwx::util::time_zone* timeZone_ {nullptr};
|
||||
|
||||
void UpdateTimeZoneLabel(const zoned_time_ zonedTime);
|
||||
std::chrono::system_clock::time_point GetTimePoint();
|
||||
void SetTimePoint(std::chrono::system_clock::time_point time);
|
||||
|
||||
void ConnectSignals();
|
||||
void UpdateAutoUpdateLabel();
|
||||
|
|
@ -61,21 +75,19 @@ AnimationDockWidget::AnimationDockWidget(QWidget* parent) :
|
|||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
// Set current date/time
|
||||
QDateTime currentDateTime = QDateTime::currentDateTimeUtc();
|
||||
QDate currentDate = currentDateTime.date();
|
||||
QTime currentTime = currentDateTime.time();
|
||||
currentTime = currentTime.addSecs(-currentTime.second() + 59);
|
||||
|
||||
ui->dateEdit->setDate(currentDate);
|
||||
ui->timeEdit->setTime(currentTime);
|
||||
ui->dateEdit->setMaximumDate(currentDateTime.date());
|
||||
p->selectedDate_ = util::SysDays(currentDate);
|
||||
p->selectedTime_ =
|
||||
std::chrono::seconds(currentTime.msecsSinceStartOfDay() / 1000);
|
||||
#if (__cpp_lib_chrono >= 201907L)
|
||||
p->timeZone_ = std::chrono::get_tzdb().locate_zone("UTC");
|
||||
#else
|
||||
p->timeZone_ = date::get_tzdb().locate_zone("UTC");
|
||||
#endif
|
||||
const std::chrono::sys_seconds currentTimePoint =
|
||||
std::chrono::floor<std::chrono::minutes>(
|
||||
std::chrono::system_clock::now());
|
||||
p->SetTimePoint(currentTimePoint);
|
||||
|
||||
// Update maximum date on a timer
|
||||
QTimer* maxDateTimer = new QTimer(this);
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory) Qt Owns this memory
|
||||
auto* maxDateTimer = new QTimer(this);
|
||||
connect(maxDateTimer,
|
||||
&QTimer::timeout,
|
||||
this,
|
||||
|
|
@ -108,6 +120,76 @@ AnimationDockWidget::~AnimationDockWidget()
|
|||
delete ui;
|
||||
}
|
||||
|
||||
void AnimationDockWidgetImpl::UpdateTimeZoneLabel(const zoned_time_ zonedTime)
|
||||
{
|
||||
#if (__cpp_lib_chrono >= 201907L)
|
||||
namespace df = std;
|
||||
static constexpr std::string_view kFormatStringTimezone = "{:%Z}";
|
||||
#else
|
||||
namespace df = date;
|
||||
static const std::string kFormatStringTimezone = "%Z";
|
||||
#endif
|
||||
const std::string timeZoneStr = df::format(kFormatStringTimezone, zonedTime);
|
||||
self_->ui->timeZoneLabel->setText(timeZoneStr.c_str());
|
||||
}
|
||||
|
||||
std::chrono::system_clock::time_point AnimationDockWidgetImpl::GetTimePoint()
|
||||
{
|
||||
#if (__cpp_lib_chrono >= 201907L)
|
||||
using namespace std::chrono;
|
||||
#else
|
||||
using namespace date;
|
||||
#endif
|
||||
|
||||
// Convert the local time, to a zoned time, to a system time
|
||||
const local_time<std::chrono::seconds> localTime =
|
||||
selectedDate_ + selectedTime_;
|
||||
const auto zonedTime =
|
||||
zoned_time<std::chrono::seconds>(timeZone_, localTime);
|
||||
const std::chrono::sys_seconds systemTime = zonedTime.get_sys_time();
|
||||
|
||||
// This is done to update it when the date changes
|
||||
UpdateTimeZoneLabel(zonedTime);
|
||||
|
||||
return systemTime;
|
||||
}
|
||||
|
||||
void AnimationDockWidgetImpl::SetTimePoint(
|
||||
std::chrono::system_clock::time_point systemTime)
|
||||
{
|
||||
#if (__cpp_lib_chrono >= 201907L)
|
||||
using namespace std::chrono;
|
||||
#else
|
||||
using namespace date;
|
||||
#endif
|
||||
// Convert the time to a local time
|
||||
auto systemTimeSeconds = time_point_cast<std::chrono::seconds>(systemTime);
|
||||
auto zonedTime =
|
||||
zoned_time<std::chrono::seconds>(timeZone_, systemTimeSeconds);
|
||||
const local_seconds localTime = zonedTime.get_local_time();
|
||||
|
||||
// Get the date and time as seperate fields
|
||||
selectedDate_ = floor<days>(localTime);
|
||||
selectedTime_ = localTime - selectedDate_;
|
||||
|
||||
// Pull out the local date and time as qt times (with c++20 this could be
|
||||
// simplified)
|
||||
auto time = QTime::fromMSecsSinceStartOfDay(static_cast<int>(
|
||||
duration_cast<std::chrono::milliseconds>(selectedTime_).count()));
|
||||
auto yearMonthDay = year_month_day(selectedDate_);
|
||||
auto date = QDate(int(yearMonthDay.year()),
|
||||
// These are always in a small range, so cast is safe
|
||||
static_cast<int>(unsigned(yearMonthDay.month())),
|
||||
static_cast<int>(unsigned(yearMonthDay.day())));
|
||||
|
||||
// Update labels
|
||||
self_->ui->timeEdit->setTime(time);
|
||||
self_->ui->dateEdit->setDate(date);
|
||||
|
||||
// Time zone almost certainly just changed, so update it
|
||||
UpdateTimeZoneLabel(zonedTime);
|
||||
}
|
||||
|
||||
void AnimationDockWidgetImpl::ConnectSignals()
|
||||
{
|
||||
// View type
|
||||
|
|
@ -142,8 +224,8 @@ void AnimationDockWidgetImpl::ConnectSignals()
|
|||
{
|
||||
if (date.isValid())
|
||||
{
|
||||
selectedDate_ = util::SysDays(date);
|
||||
Q_EMIT self_->DateTimeChanged(selectedDate_ + selectedTime_);
|
||||
selectedDate_ = util::LocalDays(date);
|
||||
Q_EMIT self_->DateTimeChanged(GetTimePoint());
|
||||
}
|
||||
});
|
||||
QObject::connect(
|
||||
|
|
@ -154,9 +236,9 @@ void AnimationDockWidgetImpl::ConnectSignals()
|
|||
{
|
||||
if (time.isValid())
|
||||
{
|
||||
selectedTime_ =
|
||||
std::chrono::seconds(time.msecsSinceStartOfDay() / 1000);
|
||||
Q_EMIT self_->DateTimeChanged(selectedDate_ + selectedTime_);
|
||||
selectedTime_ = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::milliseconds(time.msecsSinceStartOfDay()));
|
||||
Q_EMIT self_->DateTimeChanged(GetTimePoint());
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -302,6 +384,27 @@ void AnimationDockWidgetImpl::UpdateAutoUpdateLabel()
|
|||
}
|
||||
}
|
||||
|
||||
void AnimationDockWidget::UpdateTimeZone(const scwx::util::time_zone* timeZone)
|
||||
{
|
||||
// null timezone is really UTC. This simplifies other code.
|
||||
if (timeZone == nullptr)
|
||||
{
|
||||
#if (__cpp_lib_chrono >= 201907L)
|
||||
timeZone = std::chrono::get_tzdb().locate_zone("UTC");
|
||||
#else
|
||||
timeZone = date::get_tzdb().locate_zone("UTC");
|
||||
#endif
|
||||
}
|
||||
|
||||
// Get the (UTC relative) time that is selected. We want to preserve this
|
||||
// across timezone changes.
|
||||
auto currentTime = p->GetTimePoint();
|
||||
p->timeZone_ = timeZone;
|
||||
// Set the (UTC relative) time that was already selected. This ensures that
|
||||
// the actual time does not change, only the time zone.
|
||||
p->SetTimePoint(currentTime);
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <scwx/qt/types/map_types.hpp>
|
||||
#include <scwx/util/time.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
|
|
@ -32,6 +33,7 @@ public slots:
|
|||
void UpdateAnimationState(types::AnimationState state);
|
||||
void UpdateLiveState(bool isLive);
|
||||
void UpdateViewType(types::MapTime viewType);
|
||||
void UpdateTimeZone(const scwx::util::time_zone* timeZone);
|
||||
|
||||
signals:
|
||||
void ViewTypeChanged(types::MapTime viewType);
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>189</width>
|
||||
<height>264</height>
|
||||
<height>276</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
<item>
|
||||
<widget class="QDateEdit" name="dateEdit">
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="minimumDateTime">
|
||||
<datetime>
|
||||
|
|
@ -79,10 +79,10 @@
|
|||
<item>
|
||||
<widget class="QFrame" name="frame">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -100,7 +100,7 @@
|
|||
<item>
|
||||
<widget class="QTimeEdit" name="timeEdit">
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="displayFormat">
|
||||
<string>HH:mm</string>
|
||||
|
|
@ -108,7 +108,7 @@
|
|||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<widget class="QLabel" name="timeZoneLabel">
|
||||
<property name="text">
|
||||
<string>UTC</string>
|
||||
</property>
|
||||
|
|
@ -120,10 +120,10 @@
|
|||
<item>
|
||||
<widget class="QFrame" name="frame_3">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
|
|
@ -141,7 +141,7 @@
|
|||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="loopTimeSpinBox">
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> min</string>
|
||||
|
|
@ -193,7 +193,7 @@
|
|||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="loopSpeedSpinBox">
|
||||
<property name="correctionMode">
|
||||
<enum>QAbstractSpinBox::CorrectToNearestValue</enum>
|
||||
<enum>QAbstractSpinBox::CorrectionMode::CorrectToNearestValue</enum>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string>x</string>
|
||||
|
|
@ -219,10 +219,10 @@
|
|||
<item>
|
||||
<widget class="QFrame" name="frame_2">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
<enum>QFrame::Shape::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
<enum>QFrame::Shadow::Raised</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
|
|
|
|||
|
|
@ -17,6 +17,18 @@ std::chrono::sys_days SysDays(const QDate& date)
|
|||
julianEpoch);
|
||||
}
|
||||
|
||||
local_days LocalDays(const QDate& date)
|
||||
{
|
||||
#if (__cpp_lib_chrono >= 201907L)
|
||||
using namespace std::chrono;
|
||||
#else
|
||||
using namespace date;
|
||||
#endif
|
||||
auto yearMonthDay =
|
||||
year_month_day(year(date.year()), month(date.month()), day(date.day()));
|
||||
return local_days(yearMonthDay);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
#include <chrono>
|
||||
|
||||
#if (__cpp_lib_chrono < 201907L)
|
||||
# include <date/tz.h>
|
||||
#endif
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
namespace scwx
|
||||
|
|
@ -11,6 +15,12 @@ namespace qt
|
|||
namespace util
|
||||
{
|
||||
|
||||
#if (__cpp_lib_chrono >= 201907L)
|
||||
using local_days = std::chrono::local_days;
|
||||
#else
|
||||
using local_days = date::local_days;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Convert QDate to std::chrono::sys_days.
|
||||
*
|
||||
|
|
@ -20,6 +30,15 @@ namespace util
|
|||
*/
|
||||
std::chrono::sys_days SysDays(const QDate& date);
|
||||
|
||||
/**
|
||||
* @brief Convert QDate to std::chrono::local_days.
|
||||
*
|
||||
* @param [in] date Date to convert
|
||||
*
|
||||
* @return Days
|
||||
*/
|
||||
local_days LocalDays(const QDate& date);
|
||||
|
||||
} // namespace util
|
||||
} // namespace qt
|
||||
} // namespace scwx
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue