diff --git a/scwx-qt/source/scwx/qt/model/layer_model.cpp b/scwx-qt/source/scwx/qt/model/layer_model.cpp index da57d462..5645d330 100644 --- a/scwx-qt/source/scwx/qt/model/layer_model.cpp +++ b/scwx-qt/source/scwx/qt/model/layer_model.cpp @@ -44,9 +44,13 @@ static const std::string kDescriptionName_ {"description"}; static const std::string kMovableName_ {"movable"}; static const std::string kDisplayedName_ {"displayed"}; -typedef std:: - variant - LayerDescription; +typedef std::variant + LayerDescription; struct LayerInfo { @@ -59,23 +63,24 @@ struct LayerInfo typedef boost::container::stable_vector LayerVector; static const std::vector kDefaultLayers_ { - {types::LayerType::Information, types::Layer::MapOverlay, false}, - {types::LayerType::Information, types::Layer::ColorTable, false}, + {types::LayerType::Information, types::InformationLayer::MapOverlay, false}, + {types::LayerType::Information, types::InformationLayer::ColorTable, false}, + {types::LayerType::Data, types::DataLayer::RadarRange, true}, {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::Map, types::MapLayer::MapSymbology, false}, {types::LayerType::Radar, std::monostate {}, true}, - {types::LayerType::Map, types::Layer::MapUnderlay, false}, + {types::LayerType::Map, types::MapLayer::MapUnderlay, false}, }; static const std::vector kImmovableLayers_ { - {types::LayerType::Information, types::Layer::MapOverlay, false}, - {types::LayerType::Information, types::Layer::ColorTable, false}, - {types::LayerType::Map, types::Layer::MapSymbology, false}, - {types::LayerType::Map, types::Layer::MapUnderlay, false}, + {types::LayerType::Information, types::InformationLayer::MapOverlay, false}, + {types::LayerType::Information, types::InformationLayer::ColorTable, false}, + {types::LayerType::Map, types::MapLayer::MapSymbology, false}, + {types::LayerType::Map, types::MapLayer::MapUnderlay, false}, }; static const std::array kAlertPhenomena_ { @@ -206,8 +211,40 @@ void LayerModel::Impl::ReadLayerSettings() void LayerModel::Impl::ValidateLayerSettings(LayerVector& layers) { + // Validate layer properties + for (auto it = layers.begin(); it != layers.end();) + { + // If the layer is invalid, remove it + if (it->type_ == types::LayerType::Unknown || + (std::holds_alternative(it->description_) && + std::get(it->description_) == + types::DataLayer::Unknown) || + (std::holds_alternative(it->description_) && + std::get(it->description_) == + types::InformationLayer::Unknown) || + (std::holds_alternative(it->description_) && + std::get(it->description_) == + types::MapLayer::Unknown) || + (std::holds_alternative(it->description_) && + std::get(it->description_) == + awips::Phenomenon::Unknown)) + { + // Erase the current layer and continue + it = layers.erase(it); + continue; + } + + // Ensure layers are appropriately marked movable + it->movable_ = (it->type_ != types::LayerType::Information && + it->type_ != types::LayerType::Map); + + // Continue to the next layer + ++it; + } + // Validate immovable layers std::vector immovableIterators {}; + LayerVector::iterator colorTableIterator {}; LayerVector::iterator mapSymbologyIterator {}; LayerVector::iterator mapUnderlayIterator {}; for (auto& immovableLayer : kImmovableLayers_) @@ -253,15 +290,27 @@ void LayerModel::Impl::ValidateLayerSettings(LayerVector& layers) } // Store positional iterators - if (it->type_ == types::LayerType::Map) + if (it->type_ == types::LayerType::Information) { - switch (std::get(it->description_)) + switch (std::get(it->description_)) { - case types::Layer::MapSymbology: + case types::InformationLayer::ColorTable: + colorTableIterator = it; + break; + + default: + break; + } + } + else if (it->type_ == types::LayerType::Map) + { + switch (std::get(it->description_)) + { + case types::MapLayer::MapSymbology: mapSymbologyIterator = it; break; - case types::Layer::MapUnderlay: + case types::MapLayer::MapUnderlay: mapUnderlayIterator = it; break; @@ -274,7 +323,36 @@ void LayerModel::Impl::ValidateLayerSettings(LayerVector& layers) immovableIterators.push_back(it); } + // Validate data layers + std::vector dataIterators {}; + for (const auto& dataLayer : types::DataLayerIterator()) + { + // Find the data layer + auto it = std::find_if(layers.begin(), + layers.end(), + [&dataLayer](const LayerInfo& layer) + { + return layer.type_ == types::LayerType::Data && + std::get( + layer.description_) == dataLayer; + }); + + if (it == layers.end()) + { + // If this is the first data layer, insert after the color table layer, + // otherwise, insert after the previous data layer + LayerVector::iterator insertPosition = dataIterators.empty() ? + colorTableIterator + 1 : + dataIterators.back() + 1; + it = + layers.insert(insertPosition, {types::LayerType::Data, dataLayer}); + } + + dataIterators.push_back(it); + } + // Validate alert layers + std::vector alertIterators {}; for (auto& phenomenon : kAlertPhenomena_) { // Find the alert layer @@ -289,16 +367,24 @@ void LayerModel::Impl::ValidateLayerSettings(LayerVector& layers) if (it == layers.end()) { - layers.insert(mapSymbologyIterator, - {types::LayerType::Alert, phenomenon}); + // Insert before the map symbology layer + it = layers.insert(mapSymbologyIterator, + {types::LayerType::Alert, phenomenon}); } + + alertIterators.push_back(it); } - // Ensure layers are appropriately marked movable - for (auto& layer : layers) + // Validate the radar layer + auto it = std::find_if(layers.begin(), + layers.end(), + [](const LayerInfo& layer) + { return layer.type_ == types::LayerType::Radar; }); + if (it == layers.end()) { - layer.movable_ = (layer.type_ != types::LayerType::Information && - layer.type_ != types::LayerType::Map); + // Insert before the map underlay layer + it = layers.insert(mapUnderlayIterator, + {types::LayerType::Radar, std::monostate {}}); } } @@ -470,10 +556,23 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const return QString::fromStdString( std::get(layer.description_)); } - else if (std::holds_alternative(layer.description_)) + else if (std::holds_alternative( + layer.description_)) { - return QString::fromStdString(types::GetLayerName( - std::get(layer.description_))); + return QString::fromStdString(types::GetDataLayerName( + std::get(layer.description_))); + } + else if (std::holds_alternative( + layer.description_)) + { + return QString::fromStdString(types::GetInformationLayerName( + std::get(layer.description_))); + } + else if (std::holds_alternative( + layer.description_)) + { + return QString::fromStdString(types::GetMapLayerName( + std::get(layer.description_))); } else if (std::holds_alternative( layer.description_)) @@ -873,9 +972,10 @@ void LayerModel::Impl::AddPlacefile(const std::string& name) layers_.end(), [](const LayerInfo& layerInfo) { - return std::holds_alternative(layerInfo.description_) && - std::get(layerInfo.description_) == - types::Layer::ColorTable; + return std::holds_alternative( + layerInfo.description_) && + std::get(layerInfo.description_) == + types::InformationLayer::ColorTable; }); if (insertPosition != layers_.end()) { @@ -899,10 +999,21 @@ void tag_invoke(boost::json::value_from_tag, description = awips::GetPhenomenonCode( std::get(record.description_)); } - else if (std::holds_alternative(record.description_)) + else if (std::holds_alternative(record.description_)) + { + description = types::GetDataLayerName( + std::get(record.description_)); + } + else if (std::holds_alternative( + record.description_)) + { + description = types::GetInformationLayerName( + std::get(record.description_)); + } + else if (std::holds_alternative(record.description_)) { description = - types::GetLayerName(std::get(record.description_)); + types::GetMapLayerName(std::get(record.description_)); } else if (std::holds_alternative(record.description_)) { @@ -940,10 +1051,17 @@ LayerInfo tag_invoke(boost::json::value_to_tag, LayerDescription description {}; - if (layerType == types::LayerType::Map || - layerType == types::LayerType::Information) + if (layerType == types::LayerType::Map) { - description = types::GetLayer(descriptionName); + description = types::GetMapLayer(descriptionName); + } + else if (layerType == types::LayerType::Information) + { + description = types::GetInformationLayer(descriptionName); + } + else if (layerType == types::LayerType::Data) + { + description = types::GetDataLayer(descriptionName); } else if (layerType == types::LayerType::Radar) { diff --git a/scwx-qt/source/scwx/qt/types/layer_types.cpp b/scwx-qt/source/scwx/qt/types/layer_types.cpp index 24cbd989..df9e6386 100644 --- a/scwx-qt/source/scwx/qt/types/layer_types.cpp +++ b/scwx-qt/source/scwx/qt/types/layer_types.cpp @@ -17,14 +17,21 @@ static const std::unordered_map layerTypeName_ { {LayerType::Alert, "Alert"}, {LayerType::Placefile, "Placefile"}, {LayerType::Information, "Information"}, + {LayerType::Data, "Data"}, {LayerType::Unknown, "?"}}; -static const std::unordered_map layerName_ { - {Layer::MapOverlay, "Map Overlay"}, - {Layer::ColorTable, "Color Table"}, - {Layer::MapSymbology, "Map Symbology"}, - {Layer::MapUnderlay, "Map Underlay"}, - {Layer::Unknown, "?"}}; +static const std::unordered_map dataLayerName_ { + {DataLayer::RadarRange, "Radar Range"}, {DataLayer::Unknown, "?"}}; + +static const std::unordered_map + informationLayerName_ {{InformationLayer::MapOverlay, "Map Overlay"}, + {InformationLayer::ColorTable, "Color Table"}, + {InformationLayer::Unknown, "?"}}; + +static const std::unordered_map mapLayerName_ { + {MapLayer::MapSymbology, "Map Symbology"}, + {MapLayer::MapUnderlay, "Map Underlay"}, + {MapLayer::Unknown, "?"}}; LayerType GetLayerType(const std::string& name) { @@ -49,27 +56,73 @@ std::string GetLayerTypeName(LayerType layerType) return layerTypeName_.at(layerType); } -Layer GetLayer(const std::string& name) +DataLayer GetDataLayer(const std::string& name) { auto result = - std::find_if(layerName_.cbegin(), - layerName_.cend(), - [&](const std::pair& pair) -> bool + std::find_if(dataLayerName_.cbegin(), + dataLayerName_.cend(), + [&](const std::pair& pair) -> bool { return boost::iequals(pair.second, name); }); - if (result != layerName_.cend()) + if (result != dataLayerName_.cend()) { return result->first; } else { - return Layer::Unknown; + return DataLayer::Unknown; } } -std::string GetLayerName(Layer layer) +std::string GetDataLayerName(DataLayer layer) { - return layerName_.at(layer); + return dataLayerName_.at(layer); +} + +InformationLayer GetInformationLayer(const std::string& name) +{ + auto result = std::find_if( + informationLayerName_.cbegin(), + informationLayerName_.cend(), + [&](const std::pair& pair) -> bool + { return boost::iequals(pair.second, name); }); + + if (result != informationLayerName_.cend()) + { + return result->first; + } + else + { + return InformationLayer::Unknown; + } +} + +std::string GetInformationLayerName(InformationLayer layer) +{ + return informationLayerName_.at(layer); +} + +MapLayer GetMapLayer(const std::string& name) +{ + auto result = + std::find_if(mapLayerName_.cbegin(), + mapLayerName_.cend(), + [&](const std::pair& pair) -> bool + { return boost::iequals(pair.second, name); }); + + if (result != mapLayerName_.cend()) + { + return result->first; + } + else + { + return MapLayer::Unknown; + } +} + +std::string GetMapLayerName(MapLayer layer) +{ + return mapLayerName_.at(layer); } } // namespace types diff --git a/scwx-qt/source/scwx/qt/types/layer_types.hpp b/scwx-qt/source/scwx/qt/types/layer_types.hpp index 1f771879..f418986d 100644 --- a/scwx-qt/source/scwx/qt/types/layer_types.hpp +++ b/scwx-qt/source/scwx/qt/types/layer_types.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include namespace scwx @@ -16,13 +18,28 @@ enum class LayerType Alert, Placefile, Information, + Data, Unknown }; -enum class Layer +enum class DataLayer +{ + RadarRange, + Unknown +}; +typedef scwx::util:: + Iterator + DataLayerIterator; + +enum class InformationLayer { MapOverlay, ColorTable, + Unknown +}; + +enum class MapLayer +{ MapSymbology, MapUnderlay, Unknown @@ -31,8 +48,14 @@ enum class Layer LayerType GetLayerType(const std::string& name); std::string GetLayerTypeName(LayerType layerType); -Layer GetLayer(const std::string& name); -std::string GetLayerName(Layer layer); +DataLayer GetDataLayer(const std::string& name); +std::string GetDataLayerName(DataLayer layer); + +InformationLayer GetInformationLayer(const std::string& name); +std::string GetInformationLayerName(InformationLayer layer); + +MapLayer GetMapLayer(const std::string& name); +std::string GetMapLayerName(MapLayer layer); } // namespace types } // namespace qt