diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.cpp b/scwx-qt/source/scwx/qt/settings/general_settings.cpp index 330ae641..6329587a 100644 --- a/scwx-qt/source/scwx/qt/settings/general_settings.cpp +++ b/scwx-qt/source/scwx/qt/settings/general_settings.cpp @@ -12,15 +12,19 @@ namespace settings static const std::string logPrefix_ = "scwx::qt::settings::general_settings"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -static const std::string DEFAULT_DEFAULT_RADAR_SITE = "KLSX"; -static const int64_t DEFAULT_GRID_WIDTH = 1; -static const int64_t DEFAULT_GRID_HEIGHT = 1; -static const std::string DEFAULT_MAPBOX_API_KEY = "?"; +static constexpr bool kDefaultDebugEnabled_ {false}; +static const std::string kDefaultDefaultRadarSite_ {"KLSX"}; +static const std::vector kDefaultFontSizes_ {16}; +static constexpr int64_t kDefaultGridWidth_ {1}; +static constexpr int64_t kDefaultGridHeight_ {1}; +static const std::string kDefaultMapboxApiKey_ {"?"}; -static const int64_t GRID_WIDTH_MINIMUM = 1; -static const int64_t GRID_WIDTH_MAXIMUM = 2; -static const int64_t GRID_HEIGHT_MINIMUM = 1; -static const int64_t GRID_HEIGHT_MAXIMUM = 2; +static constexpr int64_t kFontSizeMinimum_ {1}; +static constexpr int64_t kFontSizeMaximum_ {72}; +static constexpr int64_t kGridWidthMinimum_ {1}; +static constexpr int64_t kGridWidthMaximum_ {2}; +static constexpr int64_t kGridHeightMinimum_ {1}; +static constexpr int64_t kGridHeightMaximum_ {2}; class GeneralSettingsImpl { @@ -31,16 +35,20 @@ public: void SetDefaults() { - defaultRadarSite_ = DEFAULT_DEFAULT_RADAR_SITE; - gridWidth_ = DEFAULT_GRID_WIDTH; - gridHeight_ = DEFAULT_GRID_HEIGHT; - mapboxApiKey_ = DEFAULT_MAPBOX_API_KEY; + debugEnabled_ = kDefaultDebugEnabled_; + defaultRadarSite_ = kDefaultDefaultRadarSite_; + fontSizes_ = kDefaultFontSizes_; + gridWidth_ = kDefaultGridWidth_; + gridHeight_ = kDefaultGridHeight_; + mapboxApiKey_ = kDefaultMapboxApiKey_; } - std::string defaultRadarSite_; - int64_t gridWidth_; - int64_t gridHeight_; - std::string mapboxApiKey_; + bool debugEnabled_; + std::string defaultRadarSite_; + std::vector fontSizes_; + int64_t gridWidth_; + int64_t gridHeight_; + std::string mapboxApiKey_; }; GeneralSettings::GeneralSettings() : p(std::make_unique()) @@ -52,11 +60,21 @@ GeneralSettings::GeneralSettings(GeneralSettings&&) noexcept = default; GeneralSettings& GeneralSettings::operator=(GeneralSettings&&) noexcept = default; +bool GeneralSettings::debug_enabled() const +{ + return p->debugEnabled_; +} + std::string GeneralSettings::default_radar_site() const { return p->defaultRadarSite_; } +std::vector GeneralSettings::font_sizes() const +{ + return p->fontSizes_; +} + int64_t GeneralSettings::grid_height() const { return p->gridHeight_; @@ -76,7 +94,9 @@ boost::json::value GeneralSettings::ToJson() const { boost::json::object json; + json["debug_enabled"] = p->debugEnabled_; json["default_radar_site"] = p->defaultRadarSite_; + json["font_sizes"] = boost::json::value_from(p->fontSizes_); json["grid_width"] = p->gridWidth_; json["grid_height"] = p->gridHeight_; json["mapbox_api_key"] = p->mapboxApiKey_; @@ -89,8 +109,6 @@ std::shared_ptr GeneralSettings::Create() std::shared_ptr generalSettings = std::make_shared(); - generalSettings->p->SetDefaults(); - return generalSettings; } @@ -102,28 +120,39 @@ GeneralSettings::Load(const boost::json::value* json, bool& jsonDirty) if (json != nullptr && json->is_object()) { + jsonDirty |= !util::json::FromJsonBool(json->as_object(), + "debug_enabled", + generalSettings->p->debugEnabled_, + kDefaultDebugEnabled_); jsonDirty |= !util::json::FromJsonString(json->as_object(), "default_radar_site", generalSettings->p->defaultRadarSite_, - DEFAULT_DEFAULT_RADAR_SITE); + kDefaultDefaultRadarSite_); + jsonDirty |= + !util::json::FromJsonInt64Array(json->as_object(), + "font_sizes", + generalSettings->p->fontSizes_, + kDefaultFontSizes_, + kFontSizeMinimum_, + kFontSizeMaximum_); jsonDirty |= !util::json::FromJsonInt64(json->as_object(), "grid_width", generalSettings->p->gridWidth_, - DEFAULT_GRID_WIDTH, - GRID_WIDTH_MINIMUM, - GRID_WIDTH_MAXIMUM); + kDefaultGridWidth_, + kGridWidthMinimum_, + kGridWidthMaximum_); jsonDirty |= !util::json::FromJsonInt64(json->as_object(), "grid_height", generalSettings->p->gridHeight_, - DEFAULT_GRID_HEIGHT, - GRID_HEIGHT_MINIMUM, - GRID_HEIGHT_MAXIMUM); + kDefaultGridHeight_, + kGridHeightMinimum_, + kGridHeightMaximum_); jsonDirty |= !util::json::FromJsonString(json->as_object(), "mapbox_api_key", generalSettings->p->mapboxApiKey_, - DEFAULT_MAPBOX_API_KEY, + kDefaultMapboxApiKey_, 1); } else @@ -146,7 +175,9 @@ GeneralSettings::Load(const boost::json::value* json, bool& jsonDirty) bool operator==(const GeneralSettings& lhs, const GeneralSettings& rhs) { - return (lhs.p->defaultRadarSite_ == rhs.p->defaultRadarSite_ && + return (lhs.p->debugEnabled_ == rhs.p->debugEnabled_ && + lhs.p->defaultRadarSite_ == rhs.p->defaultRadarSite_ && + lhs.p->fontSizes_ == rhs.p->fontSizes_ && lhs.p->gridWidth_ == rhs.p->gridWidth_ && lhs.p->gridHeight_ == rhs.p->gridHeight_ && lhs.p->mapboxApiKey_ == rhs.p->mapboxApiKey_); diff --git a/scwx-qt/source/scwx/qt/settings/general_settings.hpp b/scwx-qt/source/scwx/qt/settings/general_settings.hpp index 4a384b87..3764b4f5 100644 --- a/scwx-qt/source/scwx/qt/settings/general_settings.hpp +++ b/scwx-qt/source/scwx/qt/settings/general_settings.hpp @@ -20,16 +20,18 @@ public: explicit GeneralSettings(); ~GeneralSettings(); - GeneralSettings(const GeneralSettings&) = delete; + GeneralSettings(const GeneralSettings&) = delete; GeneralSettings& operator=(const GeneralSettings&) = delete; GeneralSettings(GeneralSettings&&) noexcept; GeneralSettings& operator=(GeneralSettings&&) noexcept; - std::string default_radar_site() const; - int64_t grid_height() const; - int64_t grid_width() const; - std::string mapbox_api_key() const; + bool debug_enabled() const; + std::string default_radar_site() const; + std::vector font_sizes() const; + int64_t grid_height() const; + int64_t grid_width() const; + std::string mapbox_api_key() const; boost::json::value ToJson() const; diff --git a/scwx-qt/source/scwx/qt/util/json.cpp b/scwx-qt/source/scwx/qt/util/json.cpp index 2931f157..fcb40cea 100644 --- a/scwx-qt/source/scwx/qt/util/json.cpp +++ b/scwx-qt/source/scwx/qt/util/json.cpp @@ -3,6 +3,7 @@ #include +#include #include #include @@ -33,6 +34,40 @@ static void PrettyPrintJson(std::ostream& os, static boost::json::value ReadJsonFile(QFile& file); static boost::json::value ReadJsonStream(std::istream& is); +bool FromJsonBool(const boost::json::object& json, + const std::string& key, + bool& value, + const bool defaultValue) +{ + const boost::json::value* jv = json.if_contains(key); + bool dirty = true; + + if (jv != nullptr) + { + if (jv->is_bool()) + { + value = boost::json::value_to(*jv); + dirty = false; + } + else + { + logger_->warn("{} is not a bool ({}), setting to default: {}", + key, + jv->kind(), + defaultValue); + value = defaultValue; + } + } + else + { + logger_->debug( + "{} is not present, setting to default: {}", key, defaultValue); + value = defaultValue; + } + + return !dirty; +} + bool FromJsonInt64(const boost::json::object& json, const std::string& key, int64_t& value, @@ -90,6 +125,92 @@ bool FromJsonInt64(const boost::json::object& json, return !dirty; } +bool FromJsonInt64Array(const boost::json::object& json, + const std::string& key, + std::vector& values, + const std::vector& defaultValues, + std::optional minValue, + std::optional maxValue) +{ + const boost::json::value* jv = json.if_contains(key); + bool dirty = true; + + if (jv != nullptr) + { + if (jv->is_array()) + { + bool validArray = false; + + try + { + values = boost::json::value_to>(*jv); + validArray = true; + } + catch (const std::exception& ex) + { + logger_->warn( + "{} is an invalid array of int64 ({}), setting to default: {}", + key, + ex.what(), + defaultValues); + values = defaultValues; + } + + if (values.empty()) + { + logger_->warn("{} is an empty array, setting to default: {}", + key, + defaultValues); + values = defaultValues; + } + else if (validArray) + { + dirty = false; + + for (auto& value : values) + { + if (minValue.has_value() && value < *minValue) + { + logger_->warn( + "{0} less than minimum ({1} < {2}), setting to: {2}", + key, + value, + *minValue); + value = *minValue; + dirty = true; + } + else if (maxValue.has_value() && value > *maxValue) + { + logger_->warn( + "{0} greater than maximum ({1} > {2}), setting to: {2}", + key, + value, + *maxValue); + value = *maxValue; + dirty = true; + } + } + } + } + else + { + logger_->warn("{} is not an array ({}), setting to default: {}", + key, + jv->kind(), + defaultValues); + values = defaultValues; + } + } + else + { + logger_->debug( + "{} is not present, setting to default: {}", key, defaultValues); + values = defaultValues; + } + + return !dirty; +} + bool FromJsonString(const boost::json::object& json, const std::string& key, std::string& value, diff --git a/scwx-qt/source/scwx/qt/util/json.hpp b/scwx-qt/source/scwx/qt/util/json.hpp index e55f16e2..3d6a7215 100644 --- a/scwx-qt/source/scwx/qt/util/json.hpp +++ b/scwx-qt/source/scwx/qt/util/json.hpp @@ -13,12 +13,22 @@ namespace util namespace json { +bool FromJsonBool(const boost::json::object& json, + const std::string& key, + bool& value, + const bool defaultValue); bool FromJsonInt64(const boost::json::object& json, const std::string& key, int64_t& value, const int64_t defaultValue, std::optional minValue, std::optional maxValue); +bool FromJsonInt64Array(const boost::json::object& json, + const std::string& key, + std::vector& values, + const std::vector& defaultValues, + std::optional minValue, + std::optional maxValue); bool FromJsonString(const boost::json::object& json, const std::string& key, std::string& value, diff --git a/test/data b/test/data index e1aea58d..b20f1c30 160000 --- a/test/data +++ b/test/data @@ -1 +1 @@ -Subproject commit e1aea58dcbb7ad961b974a6a00a83971031f4e0b +Subproject commit b20f1c3015ae88d0883734cb51ecc01372ede749 diff --git a/test/source/scwx/qt/manager/settings_manager.test.cpp b/test/source/scwx/qt/manager/settings_manager.test.cpp index cedb0a41..18791603 100644 --- a/test/source/scwx/qt/manager/settings_manager.test.cpp +++ b/test/source/scwx/qt/manager/settings_manager.test.cpp @@ -111,6 +111,8 @@ TEST_P(DefaultSettingsTest, DefaultSettings) INSTANTIATE_TEST_SUITE_P(SettingsManager, DefaultSettingsTest, testing::Values("settings-bad-types.json", + "settings-bad-types2.json", + "settings-empty-arrays.json", "settings-empty-groups.json", "settings-empty-object.json"));