mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 18:40:05 +00:00
Read layer settings from JSON
This commit is contained in:
parent
10fe904011
commit
2fe3facbd2
1 changed files with 158 additions and 60 deletions
|
|
@ -17,6 +17,7 @@
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
#include <QStyleOption>
|
#include <QStyleOption>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
#include <boost/container/stable_vector.hpp>
|
||||||
#include <boost/json.hpp>
|
#include <boost/json.hpp>
|
||||||
|
|
||||||
namespace scwx
|
namespace scwx
|
||||||
|
|
@ -47,73 +48,41 @@ typedef std::
|
||||||
variant<std::monostate, types::Layer, awips::Phenomenon, std::string>
|
variant<std::monostate, types::Layer, awips::Phenomenon, std::string>
|
||||||
LayerDescription;
|
LayerDescription;
|
||||||
|
|
||||||
|
struct LayerInfo
|
||||||
|
{
|
||||||
|
types::LayerType type_;
|
||||||
|
LayerDescription description_;
|
||||||
|
bool movable_;
|
||||||
|
std::array<bool, kMapCount_> displayed_ {true, true, true, true};
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef boost::container::stable_vector<LayerInfo> LayerVector;
|
||||||
|
|
||||||
|
static const std::vector<LayerInfo> kDefaultLayers_ {
|
||||||
|
{types::LayerType::Information, types::Layer::MapOverlay, false},
|
||||||
|
{types::LayerType::Information, types::Layer::ColorTable, false},
|
||||||
|
{types::LayerType::Alert, awips::Phenomenon::Tornado, true},
|
||||||
|
{types::LayerType::Alert, awips::Phenomenon::SnowSquall, true},
|
||||||
|
{types::LayerType::Alert, awips::Phenomenon::SevereThunderstorm, true},
|
||||||
|
{types::LayerType::Alert, awips::Phenomenon::FlashFlood, true},
|
||||||
|
{types::LayerType::Alert, awips::Phenomenon::Marine, true},
|
||||||
|
{types::LayerType::Map, types::Layer::MapSymbology, false},
|
||||||
|
{types::LayerType::Radar, std::monostate {}, true},
|
||||||
|
{types::LayerType::Map, types::Layer::MapUnderlay, false},
|
||||||
|
};
|
||||||
|
|
||||||
class LayerModel::Impl
|
class LayerModel::Impl
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct LayerInfo
|
explicit Impl(LayerModel* self) : self_ {self} {}
|
||||||
{
|
|
||||||
types::LayerType type_;
|
|
||||||
LayerDescription description_;
|
|
||||||
bool movable_;
|
|
||||||
std::array<bool, kMapCount_> displayed_ {true, true, true, true};
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<LayerInfo> LayerVector;
|
|
||||||
|
|
||||||
explicit Impl(LayerModel* self) : self_ {self}
|
|
||||||
{
|
|
||||||
layers_.emplace_back(
|
|
||||||
types::LayerType::Information, types::Layer::MapOverlay, false);
|
|
||||||
layers_.emplace_back(
|
|
||||||
types::LayerType::Information, types::Layer::ColorTable, false);
|
|
||||||
layers_.emplace_back(
|
|
||||||
types::LayerType::Alert, awips::Phenomenon::Tornado, true);
|
|
||||||
layers_.emplace_back(
|
|
||||||
types::LayerType::Alert, awips::Phenomenon::SnowSquall, true);
|
|
||||||
layers_.emplace_back(
|
|
||||||
types::LayerType::Alert, awips::Phenomenon::SevereThunderstorm, true);
|
|
||||||
layers_.emplace_back(
|
|
||||||
types::LayerType::Alert, awips::Phenomenon::FlashFlood, true);
|
|
||||||
layers_.emplace_back(
|
|
||||||
types::LayerType::Alert, awips::Phenomenon::Marine, true);
|
|
||||||
layers_.emplace_back(
|
|
||||||
types::LayerType::Map, types::Layer::MapSymbology, false);
|
|
||||||
layers_.emplace_back(types::LayerType::Radar, std::monostate {}, true);
|
|
||||||
layers_.emplace_back(
|
|
||||||
types::LayerType::Map, types::Layer::MapUnderlay, false);
|
|
||||||
}
|
|
||||||
~Impl() = default;
|
~Impl() = default;
|
||||||
|
|
||||||
void AddPlacefile(const std::string& name);
|
void AddPlacefile(const std::string& name);
|
||||||
void InitializeLayerSettings();
|
void InitializeLayerSettings();
|
||||||
|
void ReadLayerSettings();
|
||||||
void WriteLayerSettings();
|
void WriteLayerSettings();
|
||||||
|
|
||||||
friend void tag_invoke(boost::json::value_from_tag,
|
static void ValidateLayerSettings(LayerVector& layers);
|
||||||
boost::json::value& jv,
|
|
||||||
const LayerInfo& record)
|
|
||||||
{
|
|
||||||
std::string description {};
|
|
||||||
|
|
||||||
if (std::holds_alternative<awips::Phenomenon>(record.description_))
|
|
||||||
{
|
|
||||||
description = awips::GetPhenomenonCode(
|
|
||||||
std::get<awips::Phenomenon>(record.description_));
|
|
||||||
}
|
|
||||||
else if (std::holds_alternative<types::Layer>(record.description_))
|
|
||||||
{
|
|
||||||
description =
|
|
||||||
types::GetLayerName(std::get<types::Layer>(record.description_));
|
|
||||||
}
|
|
||||||
else if (std::holds_alternative<std::string>(record.description_))
|
|
||||||
{
|
|
||||||
description = std::get<std::string>(record.description_);
|
|
||||||
}
|
|
||||||
|
|
||||||
jv = {{kTypeName_, types::GetLayerTypeName(record.type_)},
|
|
||||||
{kDescriptionName_, description},
|
|
||||||
{kMovableName_, record.movable_},
|
|
||||||
{kDisplayedName_, boost::json::value_from(record.displayed_)}};
|
|
||||||
}
|
|
||||||
|
|
||||||
LayerModel* self_;
|
LayerModel* self_;
|
||||||
|
|
||||||
|
|
@ -149,6 +118,12 @@ LayerModel::LayerModel(QObject* parent) :
|
||||||
&LayerModel::HandlePlacefileUpdate);
|
&LayerModel::HandlePlacefileUpdate);
|
||||||
|
|
||||||
p->InitializeLayerSettings();
|
p->InitializeLayerSettings();
|
||||||
|
p->ReadLayerSettings();
|
||||||
|
|
||||||
|
if (p->layers_.empty())
|
||||||
|
{
|
||||||
|
p->layers_.assign(kDefaultLayers_.cbegin(), kDefaultLayers_.cend());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LayerModel::~LayerModel()
|
LayerModel::~LayerModel()
|
||||||
|
|
@ -175,6 +150,52 @@ void LayerModel::Impl::InitializeLayerSettings()
|
||||||
layerSettingsPath_ = appDataPath + "/layers.json";
|
layerSettingsPath_ = appDataPath + "/layers.json";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LayerModel::Impl::ReadLayerSettings()
|
||||||
|
{
|
||||||
|
logger_->info("Reading layer settings");
|
||||||
|
|
||||||
|
boost::json::value layerJson = nullptr;
|
||||||
|
LayerVector newLayers {};
|
||||||
|
|
||||||
|
// Determine if layer settings exists
|
||||||
|
if (std::filesystem::exists(layerSettingsPath_))
|
||||||
|
{
|
||||||
|
layerJson = util::json::ReadJsonFile(layerSettingsPath_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If layer settings was successfully read
|
||||||
|
if (layerJson != nullptr && layerJson.is_array())
|
||||||
|
{
|
||||||
|
// For each layer entry
|
||||||
|
auto& layerArray = layerJson.as_array();
|
||||||
|
for (auto& layerEntry : layerArray)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Convert layer entry to a LayerInfo record, and add to new layers
|
||||||
|
newLayers.emplace_back(
|
||||||
|
boost::json::value_to<LayerInfo>(layerEntry));
|
||||||
|
}
|
||||||
|
catch (const std::exception& ex)
|
||||||
|
{
|
||||||
|
logger_->warn("Invalid layer entry: {}", ex.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate and correct read layers
|
||||||
|
ValidateLayerSettings(newLayers);
|
||||||
|
|
||||||
|
// Assign read layers
|
||||||
|
layers_.swap(newLayers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LayerModel::Impl::ValidateLayerSettings(LayerVector& layers)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
Q_UNUSED(layers);
|
||||||
|
}
|
||||||
|
|
||||||
void LayerModel::Impl::WriteLayerSettings()
|
void LayerModel::Impl::WriteLayerSettings()
|
||||||
{
|
{
|
||||||
logger_->info("Saving layer settings");
|
logger_->info("Saving layer settings");
|
||||||
|
|
@ -555,7 +576,7 @@ bool LayerModel::dropMimeData(const QMimeData* data,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a copy of the layers to insert (don't insert in-place)
|
// Create a copy of the layers to insert (don't insert in-place)
|
||||||
std::vector<Impl::LayerInfo> newLayers {};
|
std::vector<LayerInfo> newLayers {};
|
||||||
for (auto& sourceRow : sourceRows)
|
for (auto& sourceRow : sourceRows)
|
||||||
{
|
{
|
||||||
newLayers.push_back(p->layers_.at(sourceRow));
|
newLayers.push_back(p->layers_.at(sourceRow));
|
||||||
|
|
@ -744,7 +765,7 @@ void LayerModel::Impl::AddPlacefile(const std::string& name)
|
||||||
auto insertPosition = std::find_if(
|
auto insertPosition = std::find_if(
|
||||||
layers_.begin(),
|
layers_.begin(),
|
||||||
layers_.end(),
|
layers_.end(),
|
||||||
[](const Impl::LayerInfo& layerInfo)
|
[](const LayerInfo& layerInfo)
|
||||||
{
|
{
|
||||||
return std::holds_alternative<types::Layer>(layerInfo.description_) &&
|
return std::holds_alternative<types::Layer>(layerInfo.description_) &&
|
||||||
std::get<types::Layer>(layerInfo.description_) ==
|
std::get<types::Layer>(layerInfo.description_) ==
|
||||||
|
|
@ -761,6 +782,83 @@ void LayerModel::Impl::AddPlacefile(const std::string& name)
|
||||||
self_->endInsertRows();
|
self_->endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tag_invoke(boost::json::value_from_tag,
|
||||||
|
boost::json::value& jv,
|
||||||
|
const LayerInfo& record)
|
||||||
|
{
|
||||||
|
std::string description {};
|
||||||
|
|
||||||
|
if (std::holds_alternative<awips::Phenomenon>(record.description_))
|
||||||
|
{
|
||||||
|
description = awips::GetPhenomenonCode(
|
||||||
|
std::get<awips::Phenomenon>(record.description_));
|
||||||
|
}
|
||||||
|
else if (std::holds_alternative<types::Layer>(record.description_))
|
||||||
|
{
|
||||||
|
description =
|
||||||
|
types::GetLayerName(std::get<types::Layer>(record.description_));
|
||||||
|
}
|
||||||
|
else if (std::holds_alternative<std::string>(record.description_))
|
||||||
|
{
|
||||||
|
description = std::get<std::string>(record.description_);
|
||||||
|
}
|
||||||
|
|
||||||
|
jv = {{kTypeName_, types::GetLayerTypeName(record.type_)},
|
||||||
|
{kDescriptionName_, description},
|
||||||
|
{kMovableName_, record.movable_},
|
||||||
|
{kDisplayedName_, boost::json::value_from(record.displayed_)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, std::size_t n>
|
||||||
|
std::array<T, n> tag_invoke(boost::json::value_to_tag<std::array<T, n>>,
|
||||||
|
const boost::json::value& jv)
|
||||||
|
{
|
||||||
|
std::array<T, n> array {};
|
||||||
|
boost::json::array jsonArray = jv.as_array();
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < n && i < jsonArray.size(); ++i)
|
||||||
|
{
|
||||||
|
array[i] = jsonArray[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerInfo tag_invoke(boost::json::value_to_tag<LayerInfo>,
|
||||||
|
const boost::json::value& jv)
|
||||||
|
{
|
||||||
|
const types::LayerType layerType = types::GetLayerType(
|
||||||
|
boost::json::value_to<std::string>(jv.at(kTypeName_)));
|
||||||
|
const std::string descriptionName =
|
||||||
|
boost::json::value_to<std::string>(jv.at(kDescriptionName_));
|
||||||
|
|
||||||
|
LayerDescription description {};
|
||||||
|
|
||||||
|
if (layerType == types::LayerType::Map ||
|
||||||
|
layerType == types::LayerType::Information)
|
||||||
|
{
|
||||||
|
description = types::GetLayer(descriptionName);
|
||||||
|
}
|
||||||
|
else if (layerType == types::LayerType::Radar)
|
||||||
|
{
|
||||||
|
description = std::monostate {};
|
||||||
|
}
|
||||||
|
else if (layerType == types::LayerType::Alert)
|
||||||
|
{
|
||||||
|
description = awips::GetPhenomenon(descriptionName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
description = descriptionName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return LayerInfo {
|
||||||
|
layerType,
|
||||||
|
description,
|
||||||
|
jv.at(kMovableName_).as_bool(),
|
||||||
|
boost::json::value_to<std::array<bool, 4>>(jv.at(kDisplayedName_))};
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace model
|
} // namespace model
|
||||||
} // namespace qt
|
} // namespace qt
|
||||||
} // namespace scwx
|
} // namespace scwx
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue