Add warnings provider to settings

This commit is contained in:
Dan Paulat 2024-04-25 22:24:10 -05:00
parent ea19de3e5f
commit 5ee2d10a1b
8 changed files with 234 additions and 144 deletions

View file

@ -1,5 +1,6 @@
#include <scwx/qt/manager/text_event_manager.hpp>
#include <scwx/qt/main/application.hpp>
#include <scwx/qt/settings/general_settings.hpp>
#include <scwx/awips/text_product_file.hpp>
#include <scwx/provider/warnings_provider.hpp>
#include <scwx/util/logger.hpp>
@ -32,9 +33,20 @@ public:
refreshTimer_ {threadPool_},
refreshMutex_ {},
textEventMap_ {},
textEventMutex_ {},
warningsProvider_ {kDefaultWarningsProviderUrl}
textEventMutex_ {}
{
auto& generalSettings = settings::GeneralSettings::Instance();
warningsProvider_ = std::make_shared<provider::WarningsProvider>(
generalSettings.warnings_provider().GetValue());
warningsProviderChangedCallbackUuid_ =
generalSettings.warnings_provider().RegisterValueChangedCallback(
[this](const std::string& value) {
warningsProvider_ =
std::make_shared<provider::WarningsProvider>(value);
});
boost::asio::post(threadPool_,
[this]()
{
@ -46,6 +58,10 @@ public:
~Impl()
{
settings::GeneralSettings::Instance()
.warnings_provider()
.UnregisterValueChangedCallback(warningsProviderChangedCallbackUuid_);
std::unique_lock lock(refreshMutex_);
refreshTimer_.cancel();
lock.unlock();
@ -69,7 +85,9 @@ public:
textEventMap_;
std::shared_mutex textEventMutex_;
provider::WarningsProvider warningsProvider_;
std::shared_ptr<provider::WarningsProvider> warningsProvider_ {nullptr};
boost::uuids::uuid warningsProviderChangedCallbackUuid_ {};
};
TextEventManager::TextEventManager() : p(std::make_unique<Impl>(this)) {}
@ -201,13 +219,17 @@ void TextEventManager::Impl::Refresh()
// Take a unique lock before refreshing
std::unique_lock lock(refreshMutex_);
// Take a copy of the current warnings provider to protect against change
std::shared_ptr<provider::WarningsProvider> warningsProvider =
warningsProvider_;
// Update the file listing from the warnings provider
auto [newFiles, totalFiles] = warningsProvider_.ListFiles();
auto [newFiles, totalFiles] = warningsProvider->ListFiles();
if (newFiles > 0)
{
// Load new files
auto updatedFiles = warningsProvider_.LoadUpdatedFiles();
auto updatedFiles = warningsProvider->LoadUpdatedFiles();
// Handle messages
for (auto& file : updatedFiles)

View file

@ -10,6 +10,7 @@
#include <array>
#include <boost/algorithm/string.hpp>
#include <QUrl>
namespace scwx
{
@ -25,6 +26,9 @@ class GeneralSettings::Impl
public:
explicit Impl()
{
const std::string defaultWarningsProviderValue =
"https://warnings.allisonhouse.com";
std::string defaultClockFormatValue =
scwx::util::GetClockFormatName(scwx::util::ClockFormat::_24Hour);
std::string defaultDefaultAlertActionValue =
@ -63,6 +67,7 @@ public:
theme_.SetDefault(defaultThemeValue);
trackLocation_.SetDefault(false);
updateNotificationsEnabled_.SetDefault(true);
warningsProvider_.SetDefault(defaultWarningsProviderValue);
fontSizes_.SetElementMinimum(1);
fontSizes_.SetElementMaximum(72);
@ -103,6 +108,9 @@ public:
SCWX_SETTINGS_ENUM_VALIDATOR(types::UiStyle, //
types::UiStyleIterator(),
types::GetUiStyleName));
warningsProvider_.SetValidator(
[](const std::string& value)
{ return QUrl {QString::fromStdString(value)}.isValid(); });
}
~Impl() {}
@ -128,6 +136,7 @@ public:
SettingsVariable<std::string> theme_ {"theme"};
SettingsVariable<bool> trackLocation_ {"track_location"};
SettingsVariable<bool> updateNotificationsEnabled_ {"update_notifications"};
SettingsVariable<std::string> warningsProvider_ {"warnings_provider"};
};
GeneralSettings::GeneralSettings() :
@ -153,7 +162,8 @@ GeneralSettings::GeneralSettings() :
&p->showMapLogo_,
&p->theme_,
&p->trackLocation_,
&p->updateNotificationsEnabled_});
&p->updateNotificationsEnabled_,
&p->warningsProvider_});
SetDefaults();
}
GeneralSettings::~GeneralSettings() = default;
@ -268,6 +278,11 @@ SettingsVariable<bool>& GeneralSettings::update_notifications_enabled() const
return p->updateNotificationsEnabled_;
}
SettingsVariable<std::string>& GeneralSettings::warnings_provider() const
{
return p->warningsProvider_;
}
bool GeneralSettings::Shutdown()
{
bool dataChanged = false;
@ -310,7 +325,8 @@ bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs)
lhs.p->theme_ == rhs.p->theme_ &&
lhs.p->trackLocation_ == rhs.p->trackLocation_ &&
lhs.p->updateNotificationsEnabled_ ==
rhs.p->updateNotificationsEnabled_);
rhs.p->updateNotificationsEnabled_ &&
lhs.p->warningsProvider_ == rhs.p->warningsProvider_);
}
} // namespace settings

View file

@ -45,7 +45,8 @@ public:
SettingsVariable<bool>& show_map_logo() const;
SettingsVariable<std::string>& theme() const;
SettingsVariable<bool>& track_location() const;
SettingsVariable<bool>& update_notifications_enabled() const;
SettingsVariable<bool>& update_notifications_enabled() const;
SettingsVariable<std::string>& warnings_provider() const;
static GeneralSettings& Instance();

View file

@ -133,6 +133,7 @@ public:
&defaultAlertAction_,
&clockFormat_,
&defaultTimeZone_,
&warningsProvider_,
&antiAliasingEnabled_,
&showMapAttribution_,
&showMapCenter_,
@ -232,6 +233,7 @@ public:
settings::SettingsInterface<std::string> clockFormat_ {};
settings::SettingsInterface<std::string> defaultTimeZone_ {};
settings::SettingsInterface<std::string> theme_ {};
settings::SettingsInterface<std::string> warningsProvider_ {};
settings::SettingsInterface<bool> antiAliasingEnabled_ {};
settings::SettingsInterface<bool> showMapAttribution_ {};
settings::SettingsInterface<bool> showMapCenter_ {};
@ -660,6 +662,10 @@ void SettingsDialogImpl::SetupGeneralTab()
defaultTimeZone_.SetEditWidget(self_->ui->defaultTimeZoneComboBox);
defaultTimeZone_.SetResetButton(self_->ui->resetDefaultTimeZoneButton);
warningsProvider_.SetSettingsVariable(generalSettings.warnings_provider());
warningsProvider_.SetEditWidget(self_->ui->warningsProviderLineEdit);
warningsProvider_.SetResetButton(self_->ui->resetWarningsProviderButton);
antiAliasingEnabled_.SetSettingsVariable(
generalSettings.anti_aliasing_enabled());
antiAliasingEnabled_.SetEditWidget(self_->ui->antiAliasingEnabledCheckBox);

View file

@ -128,7 +128,7 @@
<x>0</x>
<y>0</y>
<width>513</width>
<height>454</height>
<height>482</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
@ -150,10 +150,35 @@
<property name="bottomMargin">
<number>0</number>
</property>
<item row="1" column="0">
<widget class="QLabel" name="label">
<item row="8" column="2">
<widget class="QComboBox" name="defaultAlertActionComboBox"/>
</item>
<item row="6" column="4">
<widget class="QToolButton" name="resetMapboxApiKeyButton">
<property name="text">
<string>Default Radar Site</string>
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Mapbox API Key</string>
</property>
</widget>
</item>
<item row="9" column="4">
<widget class="QToolButton" name="resetClockFormatButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>
@ -164,24 +189,6 @@
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Map Provider</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QToolButton" name="resetThemeButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>
<item row="8" column="4">
<widget class="QToolButton" name="resetDefaultAlertActionButton">
<property name="text">
@ -193,32 +200,15 @@
</property>
</widget>
</item>
<item row="9" column="2">
<widget class="QComboBox" name="clockFormatComboBox"/>
</item>
<item row="6" column="0">
<widget class="QLabel" name="label_4">
<item row="9" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Mapbox API Key</string>
<string>Clock Format</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Grid Width</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>MapTiler API Key</string>
</property>
</widget>
</item>
<item row="10" column="4">
<widget class="QToolButton" name="resetDefaultTimeZoneButton">
<item row="2" column="4">
<widget class="QToolButton" name="resetGridWidthButton">
<property name="text">
<string>...</string>
</property>
@ -228,11 +218,8 @@
</property>
</widget>
</item>
<item row="8" column="2">
<widget class="QComboBox" name="defaultAlertActionComboBox"/>
</item>
<item row="7" column="4">
<widget class="QToolButton" name="resetMapTilerApiKeyButton">
<item row="1" column="4">
<widget class="QToolButton" name="resetRadarSiteButton">
<property name="text">
<string>...</string>
</property>
@ -242,6 +229,13 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Grid Height</string>
</property>
</widget>
</item>
<item row="3" column="4">
<widget class="QToolButton" name="resetGridHeightButton">
<property name="text">
@ -253,11 +247,24 @@
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="radarSiteComboBox"/>
<item row="11" column="2">
<widget class="QLineEdit" name="warningsProviderLineEdit"/>
</item>
<item row="1" column="4">
<widget class="QToolButton" name="resetRadarSiteButton">
<item row="0" column="2">
<widget class="QComboBox" name="themeComboBox"/>
</item>
<item row="11" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Warnings Provider</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="gridWidthSpinBox"/>
</item>
<item row="5" column="4">
<widget class="QToolButton" name="resetMapProviderButton">
<property name="text">
<string>...</string>
</property>
@ -274,78 +281,8 @@
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Theme</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QComboBox" name="themeComboBox"/>
</item>
<item row="10" column="2">
<widget class="QComboBox" name="defaultTimeZoneComboBox"/>
</item>
<item row="1" column="3">
<widget class="QToolButton" name="radarSiteSelectButton">
<property name="text">
<string>...</string>
</property>
</widget>
</item>
<item row="7" column="2">
<widget class="QLineEdit" name="mapTilerApiKeyLineEdit">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="defaultAlertActionLabel">
<property name="text">
<string>Default Alert Action</string>
</property>
</widget>
</item>
<item row="2" column="4">
<widget class="QToolButton" name="resetGridWidthButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QComboBox" name="mapProviderComboBox"/>
</item>
<item row="5" column="4">
<widget class="QToolButton" name="resetMapProviderButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>
<item row="6" column="4">
<widget class="QToolButton" name="resetMapboxApiKeyButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>
<item row="9" column="4">
<widget class="QToolButton" name="resetClockFormatButton">
<item row="0" column="4">
<widget class="QToolButton" name="resetThemeButton">
<property name="text">
<string>...</string>
</property>
@ -358,20 +295,104 @@
<item row="3" column="2">
<widget class="QSpinBox" name="gridHeightSpinBox"/>
</item>
<item row="2" column="2">
<widget class="QSpinBox" name="gridWidthSpinBox"/>
<item row="9" column="2">
<widget class="QComboBox" name="clockFormatComboBox"/>
</item>
<item row="9" column="0">
<widget class="QLabel" name="label_20">
<item row="10" column="2">
<widget class="QComboBox" name="defaultTimeZoneComboBox"/>
</item>
<item row="1" column="3">
<widget class="QToolButton" name="radarSiteSelectButton">
<property name="text">
<string>Clock Format</string>
<string>...</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<item row="0" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Grid Height</string>
<string>Theme</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>MapTiler API Key</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>Map Provider</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="defaultAlertActionLabel">
<property name="text">
<string>Default Alert Action</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Grid Width</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Default Radar Site</string>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QComboBox" name="mapProviderComboBox"/>
</item>
<item row="7" column="4">
<widget class="QToolButton" name="resetMapTilerApiKeyButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QComboBox" name="radarSiteComboBox"/>
</item>
<item row="7" column="2">
<widget class="QLineEdit" name="mapTilerApiKeyLineEdit">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="10" column="4">
<widget class="QToolButton" name="resetDefaultTimeZoneButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>
<item row="11" column="4">
<widget class="QToolButton" name="resetWarningsProviderButton">
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset resource="../../../../scwx-qt.qrc">
<normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</normaloff>:/res/icons/font-awesome-6/rotate-left-solid.svg</iconset>
</property>
</widget>
</item>

@ -1 +1 @@
Subproject commit ab32df5b0731d70aa5b977453c9aa4786eb0bd3f
Subproject commit e350743fd8ca6858ce49a22bb8e40a0c6710ca86

View file

@ -8,12 +8,18 @@ namespace network
{
static const std::string& kDefaultUrl {"https://warnings.allisonhouse.com"};
static const std::string& kAlternateUrl {"http://warnings.cod.edu"};
static const std::string& kAlternateUrl {"https://warnings.cod.edu"};
TEST(DirList, GetDefaultUrl)
{
auto records = DirList(kDefaultUrl);
// No records, skip test
if (records.size() == 0)
{
GTEST_SKIP();
}
EXPECT_GT(records.size(), 0);
}
@ -21,6 +27,12 @@ TEST(DirList, GetAlternateUrl)
{
auto records = DirList(kAlternateUrl);
// No records, skip test
if (records.size() == 0)
{
GTEST_SKIP();
}
EXPECT_GT(records.size(), 0);
}

View file

@ -8,7 +8,7 @@ namespace provider
{
static const std::string& kDefaultUrl {"https://warnings.allisonhouse.com"};
static const std::string& kAlternateUrl {"http://warnings.cod.edu"};
static const std::string& kAlternateUrl {"https://warnings.cod.edu"};
class WarningsProviderTest : public testing::TestWithParam<std::string>
{
@ -19,6 +19,12 @@ TEST_P(WarningsProviderTest, ListFiles)
auto [newObjects, totalObjects] = provider.ListFiles();
// No objects, skip test
if (totalObjects == 0)
{
GTEST_SKIP();
}
EXPECT_GT(newObjects, 0);
EXPECT_GT(totalObjects, 0);
EXPECT_EQ(newObjects, totalObjects);
@ -31,6 +37,12 @@ TEST_P(WarningsProviderTest, LoadUpdatedFiles)
auto [newObjects, totalObjects] = provider.ListFiles();
auto updatedFiles = provider.LoadUpdatedFiles();
// No objects, skip test
if (totalObjects == 0)
{
GTEST_SKIP();
}
EXPECT_GT(newObjects, 0);
EXPECT_GT(totalObjects, 0);
EXPECT_EQ(newObjects, totalObjects);