From 14d69120146d1ac4dd7b96e2cebe72c53c761485 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Fri, 13 Oct 2023 13:04:48 -0500 Subject: [PATCH] Additional layer model row population, properties --- scwx-qt/source/scwx/qt/model/layer_model.cpp | 225 ++++++++++++------- scwx-qt/source/scwx/qt/model/layer_model.hpp | 10 +- scwx-qt/source/scwx/qt/types/map_types.cpp | 23 ++ scwx-qt/source/scwx/qt/types/map_types.hpp | 19 ++ 4 files changed, 187 insertions(+), 90 deletions(-) diff --git a/scwx-qt/source/scwx/qt/model/layer_model.cpp b/scwx-qt/source/scwx/qt/model/layer_model.cpp index 3a95f15c..6c3ac23d 100644 --- a/scwx-qt/source/scwx/qt/model/layer_model.cpp +++ b/scwx-qt/source/scwx/qt/model/layer_model.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -27,35 +28,53 @@ static constexpr int kLastColumn = static_cast(LayerModel::Column::Description); static constexpr int kNumColumns = kLastColumn - kFirstColumn + 1; -static const std::unordered_map - layerTypeNames_ {{LayerModel::LayerType::Map, "Map"}, - {LayerModel::LayerType::Radar, "Radar"}, - {LayerModel::LayerType::Alert, "Alert"}, - {LayerModel::LayerType::Placefile, "Placefile"}}; +static constexpr std::size_t kMapCount_ = 4u; -typedef std::variant - LayerDescription; -typedef boost::container::devector< - std::pair> - LayerVector; +typedef std:: + variant + LayerDescription; class LayerModel::Impl { public: - explicit Impl() + struct LayerInfo { - layers_.emplace_back(LayerType::Alert, awips::Phenomenon::Tornado); - layers_.emplace_back(LayerType::Alert, awips::Phenomenon::SnowSquall); - layers_.emplace_back(LayerType::Alert, - awips::Phenomenon::SevereThunderstorm); - layers_.emplace_back(LayerType::Alert, awips::Phenomenon::FlashFlood); - layers_.emplace_back(LayerType::Alert, awips::Phenomenon::Marine); - layers_.emplace_back(LayerType::Map, "Map Overlay"); - layers_.emplace_back(LayerType::Radar, std::monostate {}); - layers_.emplace_back(LayerType::Map, "Map Underlay"); + types::LayerType type_; + LayerDescription description_; + bool movable_; + std::array displayed_ {true, true, true, true}; + }; + + typedef boost::container::devector 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; + void AddPlacefile(const std::string& name); + + LayerModel* self_; + std::shared_ptr placefileManager_ { manager::PlacefileManager::Instance()}; @@ -63,7 +82,7 @@ public: }; LayerModel::LayerModel(QObject* parent) : - QAbstractTableModel(parent), p(std::make_unique()) + QAbstractTableModel(parent), p(std::make_unique(this)) { connect(p->placefileManager_.get(), &manager::PlacefileManager::PlacefileEnabled, @@ -101,13 +120,25 @@ Qt::ItemFlags LayerModel::flags(const QModelIndex& index) const { Qt::ItemFlags flags = QAbstractTableModel::flags(index); + if (!index.isValid() || index.row() < 0 || + static_cast(index.row()) >= p->layers_.size()) + { + return flags; + } + + const auto& layer = p->layers_.at(index.row()); + switch (index.column()) { case static_cast(Column::DisplayMap1): case static_cast(Column::DisplayMap2): case static_cast(Column::DisplayMap3): case static_cast(Column::DisplayMap4): - flags |= Qt::ItemFlag::ItemIsUserCheckable | Qt::ItemFlag::ItemIsEditable; + if (layer.type_ != types::LayerType::Map) + { + flags |= + Qt::ItemFlag::ItemIsUserCheckable | Qt::ItemFlag::ItemIsEditable; + } break; default: @@ -131,8 +162,7 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const return QVariant(); } - const auto& layer = p->layers_.at(index.row()); - bool enabled = true; // TODO + const auto& layer = p->layers_.at(index.row()); switch (index.column()) { @@ -147,15 +177,21 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const case static_cast(Column::DisplayMap2): case static_cast(Column::DisplayMap3): case static_cast(Column::DisplayMap4): - // TODO - if (role == Qt::ItemDataRole::ToolTipRole) + if (layer.type_ != types::LayerType::Map) { - return enabled ? displayedString : hiddenString; - } - else if (role == Qt::ItemDataRole::CheckStateRole) - { - return static_cast(enabled ? Qt::CheckState::Checked : - Qt::CheckState::Unchecked); + bool displayed = + layer.displayed_[index.column() - + static_cast(Column::DisplayMap1)]; + + if (role == Qt::ItemDataRole::ToolTipRole) + { + return displayed ? displayedString : hiddenString; + } + else if (role == Qt::ItemDataRole::CheckStateRole) + { + return static_cast(displayed ? Qt::CheckState::Checked : + Qt::CheckState::Unchecked); + } } break; @@ -163,7 +199,7 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const if (role == Qt::ItemDataRole::DisplayRole || role == Qt::ItemDataRole::ToolTipRole) { - return QString::fromStdString(layerTypeNames_.at(layer.first)); + return QString::fromStdString(types::GetLayerTypeName(layer.type_)); } break; @@ -171,17 +207,13 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const if (role == Qt::ItemDataRole::DisplayRole || role == Qt::ItemDataRole::ToolTipRole) { - if (layer.first == LayerType::Placefile) + if (layer.type_ == types::LayerType::Placefile) { return p->placefileManager_->placefile_enabled( - std::get(layer.second)) ? + std::get(layer.description_)) ? enabledString : disabledString; } - else - { - return enabledString; - } } break; @@ -189,10 +221,11 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const if (role == Qt::ItemDataRole::DisplayRole || role == Qt::ItemDataRole::ToolTipRole) { - if (layer.first == LayerType::Placefile) + if (layer.type_ == types::LayerType::Placefile) { - std::string placefileName = std::get(layer.second); - std::string description = placefileName; + std::string placefileName = + std::get(layer.description_); + std::string description = placefileName; std::string title = p->placefileManager_->placefile_title(placefileName); if (!title.empty()) @@ -204,15 +237,21 @@ QVariant LayerModel::data(const QModelIndex& index, int role) const } else { - if (std::holds_alternative(layer.second)) + if (std::holds_alternative(layer.description_)) { return QString::fromStdString( - std::get(layer.second)); + std::get(layer.description_)); } - else if (std::holds_alternative(layer.second)) + else if (std::holds_alternative(layer.description_)) + { + return QString::fromStdString(types::GetLayerName( + std::get(layer.description_))); + } + else if (std::holds_alternative( + layer.description_)) { return QString::fromStdString(awips::GetPhenomenonText( - std::get(layer.second))); + std::get(layer.description_))); } } } @@ -321,8 +360,8 @@ bool LayerModel::setData(const QModelIndex& index, return false; } - const auto& layer = p->layers_.at(index.row()); - bool result = false; + auto& layer = p->layers_.at(index.row()); + bool result = false; switch (index.column()) { @@ -332,9 +371,10 @@ bool LayerModel::setData(const QModelIndex& index, case static_cast(Column::DisplayMap4): if (role == Qt::ItemDataRole::CheckStateRole) { - // TODO - Q_UNUSED(layer); - Q_UNUSED(value); + layer.displayed_[index.column() - + static_cast(Column::DisplayMap1)] = + value.toBool(); + result = true; } break; @@ -352,13 +392,14 @@ bool LayerModel::setData(const QModelIndex& index, void LayerModel::HandlePlacefileRemoved(const std::string& name) { - auto it = std::find_if(p->layers_.begin(), - p->layers_.end(), - [&name](const auto& layer) - { - return layer.first == LayerType::Placefile && - std::get(layer.second) == name; - }); + auto it = + std::find_if(p->layers_.begin(), + p->layers_.end(), + [&name](const auto& layer) + { + return layer.type_ == types::LayerType::Placefile && + std::get(layer.description_) == name; + }); if (it != p->layers_.end()) { @@ -374,14 +415,14 @@ void LayerModel::HandlePlacefileRemoved(const std::string& name) void LayerModel::HandlePlacefileRenamed(const std::string& oldName, const std::string& newName) { - auto it = - std::find_if(p->layers_.begin(), - p->layers_.end(), - [&oldName](const auto& layer) - { - return layer.first == LayerType::Placefile && - std::get(layer.second) == oldName; - }); + auto it = std::find_if( + p->layers_.begin(), + p->layers_.end(), + [&oldName](const auto& layer) + { + return layer.type_ == types::LayerType::Placefile && + std::get(layer.description_) == oldName; + }); if (it != p->layers_.end()) { @@ -391,28 +432,27 @@ void LayerModel::HandlePlacefileRenamed(const std::string& oldName, QModelIndex bottomRight = createIndex(row, kLastColumn); // Rename placefile - it->second = newName; + it->description_ = newName; Q_EMIT dataChanged(topLeft, bottomRight); } else { - // Placefile is new, prepend row - beginInsertRows(QModelIndex(), 0, 0); - p->layers_.push_front({LayerType::Placefile, newName}); - endInsertRows(); + // Placefile doesn't exist, add row + p->AddPlacefile(newName); } } void LayerModel::HandlePlacefileUpdate(const std::string& name) { - auto it = std::find_if(p->layers_.begin(), - p->layers_.end(), - [&name](const auto& layer) - { - return layer.first == LayerType::Placefile && - std::get(layer.second) == name; - }); + auto it = + std::find_if(p->layers_.begin(), + p->layers_.end(), + [&name](const auto& layer) + { + return layer.type_ == types::LayerType::Placefile && + std::get(layer.description_) == name; + }); if (it != p->layers_.end()) { @@ -425,13 +465,34 @@ void LayerModel::HandlePlacefileUpdate(const std::string& name) } else { - // Placefile is new, prepend row - beginInsertRows(QModelIndex(), 0, 0); - p->layers_.push_front({LayerType::Placefile, name}); - endInsertRows(); + // Placefile doesn't exist, add row + p->AddPlacefile(name); } } +void LayerModel::Impl::AddPlacefile(const std::string& name) +{ + // Insert after color table + auto insertPosition = std::find_if( + layers_.begin(), + layers_.end(), + [](const Impl::LayerInfo& layerInfo) + { + return std::holds_alternative(layerInfo.description_) && + std::get(layerInfo.description_) == + types::Layer::ColorTable; + }); + if (insertPosition != layers_.end()) + { + ++insertPosition; + } + + // Placefile is new, add row + self_->beginInsertRows(QModelIndex(), 0, 0); + layers_.insert(insertPosition, {types::LayerType::Placefile, name}); + self_->endInsertRows(); +} + } // namespace model } // namespace qt } // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/layer_model.hpp b/scwx-qt/source/scwx/qt/model/layer_model.hpp index 0a0a46bd..91e3a9f0 100644 --- a/scwx-qt/source/scwx/qt/model/layer_model.hpp +++ b/scwx-qt/source/scwx/qt/model/layer_model.hpp @@ -17,6 +17,8 @@ namespace model class LayerModel : public QAbstractTableModel { + Q_DISABLE_COPY_MOVE(LayerModel) + public: enum class Column : int { @@ -32,14 +34,6 @@ public: typedef scwx::util::Iterator ColumnIterator; - enum class LayerType - { - Map, - Radar, - Alert, - Placefile - }; - explicit LayerModel(QObject* parent = nullptr); ~LayerModel(); diff --git a/scwx-qt/source/scwx/qt/types/map_types.cpp b/scwx-qt/source/scwx/qt/types/map_types.cpp index d3ea6bc0..57612242 100644 --- a/scwx-qt/source/scwx/qt/types/map_types.cpp +++ b/scwx-qt/source/scwx/qt/types/map_types.cpp @@ -9,9 +9,32 @@ namespace qt namespace types { +static const std::unordered_map layerTypeName_ { + {types::LayerType::Map, "Map"}, + {types::LayerType::Radar, "Radar"}, + {types::LayerType::Alert, "Alert"}, + {types::LayerType::Placefile, "Placefile"}, + {types::LayerType::Information, "Information"}}; + +static const std::unordered_map layerName_ { + {types::Layer::MapOverlay, "Map Overlay"}, + {types::Layer::ColorTable, "Color Table"}, + {types::Layer::MapSymbology, "Map Symbology"}, + {types::Layer::MapUnderlay, "Map Underlay"}}; + static const std::unordered_map mapTimeName_ { {MapTime::Live, "Live"}, {MapTime::Archive, "Archive"}}; +std::string GetLayerTypeName(LayerType layerType) +{ + return layerTypeName_.at(layerType); +} + +std::string GetLayerName(Layer layer) +{ + return layerName_.at(layer); +} + std::string GetMapTimeName(MapTime mapTime) { return mapTimeName_.at(mapTime); diff --git a/scwx-qt/source/scwx/qt/types/map_types.hpp b/scwx-qt/source/scwx/qt/types/map_types.hpp index 5853a188..d9dd5548 100644 --- a/scwx-qt/source/scwx/qt/types/map_types.hpp +++ b/scwx-qt/source/scwx/qt/types/map_types.hpp @@ -9,6 +9,23 @@ namespace qt namespace types { +enum class LayerType +{ + Map, + Radar, + Alert, + Placefile, + Information +}; + +enum class Layer +{ + MapOverlay, + ColorTable, + MapSymbology, + MapUnderlay +}; + enum class AnimationState { Play, @@ -29,6 +46,8 @@ enum class NoUpdateReason InvalidData }; +std::string GetLayerTypeName(LayerType layerType); +std::string GetLayerName(Layer layer); std::string GetMapTimeName(MapTime mapTime); } // namespace types