diff --git a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp index 0ad34b9f..dd6215d0 100644 --- a/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/text_event_manager.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -32,9 +33,20 @@ public: refreshTimer_ {threadPool_}, refreshMutex_ {}, textEventMap_ {}, - textEventMutex_ {}, - warningsProvider_ {kDefaultWarningsProviderUrl} + textEventMutex_ {} { + auto& generalSettings = settings::GeneralSettings::Instance(); + + warningsProvider_ = std::make_shared( + generalSettings.warnings_provider().GetValue()); + + warningsProviderChangedCallbackUuid_ = + generalSettings.warnings_provider().RegisterValueChangedCallback( + [this](const std::string& value) { + warningsProvider_ = + std::make_shared(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 warningsProvider_ {nullptr}; + + boost::uuids::uuid warningsProviderChangedCallbackUuid_ {}; }; TextEventManager::TextEventManager() : p(std::make_unique(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 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) diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.cpp b/scwx-qt/source/scwx/qt/settings/general_settings.cpp index 1a670b9f..3bcb3708 100644 --- a/scwx-qt/source/scwx/qt/settings/general_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/general_settings.cpp @@ -10,6 +10,7 @@ #include #include +#include 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 theme_ {"theme"}; SettingsVariable trackLocation_ {"track_location"}; SettingsVariable updateNotificationsEnabled_ {"update_notifications"}; + SettingsVariable 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& GeneralSettings::update_notifications_enabled() const return p->updateNotificationsEnabled_; } +SettingsVariable& 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 diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.hpp b/scwx-qt/source/scwx/qt/settings/general_settings.hpp index 73d2963e..65c3536f 100644 --- a/scwx-qt/source/scwx/qt/settings/general_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/general_settings.hpp @@ -45,7 +45,8 @@ public: SettingsVariable& show_map_logo() const; SettingsVariable& theme() const; SettingsVariable& track_location() const; - SettingsVariable& update_notifications_enabled() const; + SettingsVariable& update_notifications_enabled() const; + SettingsVariable& warnings_provider() const; static GeneralSettings& Instance(); diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp index 30cd4bcb..bdf39f34 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.cpp @@ -133,6 +133,7 @@ public: &defaultAlertAction_, &clockFormat_, &defaultTimeZone_, + &warningsProvider_, &antiAliasingEnabled_, &showMapAttribution_, &showMapCenter_, @@ -232,6 +233,7 @@ public: settings::SettingsInterface clockFormat_ {}; settings::SettingsInterface defaultTimeZone_ {}; settings::SettingsInterface theme_ {}; + settings::SettingsInterface warningsProvider_ {}; settings::SettingsInterface antiAliasingEnabled_ {}; settings::SettingsInterface showMapAttribution_ {}; settings::SettingsInterface 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); diff --git a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui index a6cf6804..0b60427e 100644 --- a/scwx-qt/source/scwx/qt/ui/settings_dialog.ui +++ b/scwx-qt/source/scwx/qt/ui/settings_dialog.ui @@ -128,7 +128,7 @@ 0 0 513 - 454 + 482 @@ -150,10 +150,35 @@ 0 - - + + + + + - Default Radar Site + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + Mapbox API Key + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg @@ -164,24 +189,6 @@ - - - - Map Provider - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - @@ -193,32 +200,15 @@ - - - - - + + - Mapbox API Key + Clock Format - - - - Grid Width - - - - - - - MapTiler API Key - - - - - + + ... @@ -228,11 +218,8 @@ - - - - - + + ... @@ -242,6 +229,13 @@ + + + + Grid Height + + + @@ -253,11 +247,24 @@ - - + + - - + + + + + + + Warnings Provider + + + + + + + + ... @@ -274,78 +281,8 @@ - - - - Theme - - - - - - - - - - - - - ... - - - - - - - QLineEdit::Password - - - - - - - Default Alert Action - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - - - ... - - - - :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg - - - - - + + ... @@ -358,20 +295,104 @@ - - + + - - + + + + + - Clock Format + ... - - + + - Grid Height + Theme + + + + + + + MapTiler API Key + + + + + + + Map Provider + + + + + + + Default Alert Action + + + + + + + Grid Width + + + + + + + Default Radar Site + + + + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + + + + QLineEdit::Password + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg + + + + + + + ... + + + + :/res/icons/font-awesome-6/rotate-left-solid.svg:/res/icons/font-awesome-6/rotate-left-solid.svg diff --git a/test/data b/test/data index ab32df5b..e350743f 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit ab32df5b0731d70aa5b977453c9aa4786eb0bd3f +Subproject commit e350743fd8ca6858ce49a22bb8e40a0c6710ca86 diff --git a/test/source/scwx/network/dir_list.test.cpp b/test/source/scwx/network/dir_list.test.cpp index 9bac666a..03a86a9d 100644 --- a/test/source/scwx/network/dir_list.test.cpp +++ b/test/source/scwx/network/dir_list.test.cpp @@ -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); } diff --git a/test/source/scwx/provider/warnings_provider.test.cpp b/test/source/scwx/provider/warnings_provider.test.cpp index bc762dd6..78ef9b95 100644 --- a/test/source/scwx/provider/warnings_provider.test.cpp +++ b/test/source/scwx/provider/warnings_provider.test.cpp @@ -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 { @@ -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);