Update displayed layers when the layer model changes

This commit is contained in:
Dan Paulat 2023-11-05 06:03:54 -06:00
parent c81d9d9ba6
commit 2b6f70697c
5 changed files with 142 additions and 181 deletions

View file

@ -23,7 +23,8 @@ namespace map
static const std::string logPrefix_ = "scwx::qt::map::alert_layer"; static const std::string logPrefix_ = "scwx::qt::map::alert_layer";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
static void AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map, static std::vector<std::string>
AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
awips::Phenomenon phenomenon, awips::Phenomenon phenomenon,
bool alertActive, bool alertActive,
const QString& beforeLayer); const QString& beforeLayer);
@ -139,15 +140,17 @@ AlertLayer::AlertLayer(std::shared_ptr<MapContext> context) :
AlertLayer::~AlertLayer() = default; AlertLayer::~AlertLayer() = default;
void AlertLayer::AddLayers(awips::Phenomenon phenomenon, std::vector<std::string> AlertLayer::AddLayers(awips::Phenomenon phenomenon,
const std::string& before) const std::string& before)
{ {
logger_->debug("AddLayers(): {}", awips::GetPhenomenonCode(phenomenon)); logger_->debug("AddLayers(): {}", awips::GetPhenomenonCode(phenomenon));
std::vector<std::string> layers {};
auto map = p->context_->map().lock(); auto map = p->context_->map().lock();
if (map == nullptr) if (map == nullptr)
{ {
return; return layers;
} }
const QString beforeLayer {QString::fromStdString(before)}; const QString beforeLayer {QString::fromStdString(before)};
@ -156,31 +159,11 @@ void AlertLayer::AddLayers(awips::Phenomenon phenomenon,
for (bool alertActive : {false, true}) for (bool alertActive : {false, true})
{ {
p->UpdateSource(phenomenon, alertActive); p->UpdateSource(phenomenon, alertActive);
AddAlertLayer(map, phenomenon, alertActive, beforeLayer); auto newLayers = AddAlertLayer(map, phenomenon, alertActive, beforeLayer);
} layers.insert(layers.end(), newLayers.cbegin(), newLayers.cend());
}
void AlertLayer::AddLayers(const std::string& before)
{
logger_->debug("AddLayers()");
auto map = p->context_->map().lock();
if (map == nullptr)
{
return;
} }
const QString beforeLayer {QString::fromStdString(before)}; return layers;
// Add/update GeoJSON sources and create layers
for (auto& phenomenon : kAlertPhenomena_)
{
for (bool alertActive : {false, true})
{
p->UpdateSource(phenomenon, alertActive);
AddAlertLayer(map, phenomenon, alertActive, beforeLayer);
}
}
} }
std::list<QMapLibreGL::Feature>* std::list<QMapLibreGL::Feature>*
@ -387,7 +370,8 @@ std::shared_ptr<AlertLayerHandler> AlertLayerHandler::Instance()
return alertLayerHandler; return alertLayerHandler;
} }
static void AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map, static std::vector<std::string>
AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
awips::Phenomenon phenomenon, awips::Phenomenon phenomenon,
bool alertActive, bool alertActive,
const QString& beforeLayer) const QString& beforeLayer)
@ -438,6 +422,8 @@ static void AddAlertLayer(std::shared_ptr<QMapLibreGL::Map> map,
.arg(outlineColor[3])); .arg(outlineColor[3]));
map->setPaintProperty(fgLayerId, "line-opacity", QString("%1").arg(opacity)); map->setPaintProperty(fgLayerId, "line-opacity", QString("%1").arg(opacity));
map->setPaintProperty(fgLayerId, "line-width", "3"); map->setPaintProperty(fgLayerId, "line-width", "3");
return {bgLayerId.toStdString(), fgLayerId.toStdString()};
} }
static QMapLibreGL::Feature static QMapLibreGL::Feature

View file

@ -4,6 +4,8 @@
#include <scwx/qt/map/map_context.hpp> #include <scwx/qt/map/map_context.hpp>
#include <memory> #include <memory>
#include <string>
#include <vector>
namespace scwx namespace scwx
{ {
@ -20,8 +22,8 @@ public:
explicit AlertLayer(std::shared_ptr<MapContext> context); explicit AlertLayer(std::shared_ptr<MapContext> context);
~AlertLayer(); ~AlertLayer();
void AddLayers(awips::Phenomenon phenomenon, const std::string& before = {}); std::vector<std::string> AddLayers(awips::Phenomenon phenomenon,
void AddLayers(const std::string& before = {}); const std::string& before = {});
private: private:
std::unique_ptr<AlertLayerImpl> p; std::unique_ptr<AlertLayerImpl> p;

View file

@ -131,7 +131,7 @@ public:
const std::string& before = {}); const std::string& before = {});
void AddLayers(); void AddLayers();
void AddPlacefileLayer(const std::string& placefileName, void AddPlacefileLayer(const std::string& placefileName,
const std::string& before = "colorTable"); const std::string& before);
void ConnectSignals(); void ConnectSignals();
void ImGuiCheckFonts(); void ImGuiCheckFonts();
void InitializeNewRadarProductView(const std::string& colorPalette); void InitializeNewRadarProductView(const std::string& colorPalette);
@ -139,11 +139,9 @@ public:
void RadarProductManagerDisconnect(); void RadarProductManagerDisconnect();
void RadarProductViewConnect(); void RadarProductViewConnect();
void RadarProductViewDisconnect(); void RadarProductViewDisconnect();
void RemovePlacefileLayer(const std::string& placefileName);
void RunMousePicking(); void RunMousePicking();
void SetRadarSite(const std::string& radarSite); void SetRadarSite(const std::string& radarSite);
void UpdateLoadedStyle(); void UpdateLoadedStyle();
void UpdatePlacefileLayers();
bool UpdateStoredMapParameters(); bool UpdateStoredMapParameters();
std::string FindMapSymbologyLayer(); std::string FindMapSymbologyLayer();
@ -174,6 +172,9 @@ public:
bool imGuiRendererInitialized_; bool imGuiRendererInitialized_;
std::uint64_t imGuiFontsBuildCount_ {}; std::uint64_t imGuiFontsBuildCount_ {};
std::shared_ptr<model::LayerModel> layerModel_ {
model::LayerModel::Instance()};
std::shared_ptr<manager::PlacefileManager> placefileManager_ { std::shared_ptr<manager::PlacefileManager> placefileManager_ {
manager::PlacefileManager::Instance()}; manager::PlacefileManager::Instance()};
std::shared_ptr<manager::RadarProductManager> radarProductManager_; std::shared_ptr<manager::RadarProductManager> radarProductManager_;
@ -186,7 +187,6 @@ public:
std::shared_ptr<PlacefileLayer> placefileLayer_; std::shared_ptr<PlacefileLayer> placefileLayer_;
std::shared_ptr<ColorTableLayer> colorTableLayer_; std::shared_ptr<ColorTableLayer> colorTableLayer_;
std::set<std::string> enabledPlacefiles_ {};
std::list<std::shared_ptr<PlacefileLayer>> placefileLayers_ {}; std::list<std::shared_ptr<PlacefileLayer>> placefileLayers_ {};
bool autoRefreshEnabled_; bool autoRefreshEnabled_;
@ -237,62 +237,59 @@ MapWidget::~MapWidget()
void MapWidgetImpl::ConnectSignals() void MapWidgetImpl::ConnectSignals()
{ {
connect(placefileManager_.get(),
&manager::PlacefileManager::PlacefileEnabled,
widget_,
[this](const std::string& name, bool enabled)
{
if (enabled && !enabledPlacefiles_.contains(name))
{
// Placefile enabled, add layer
enabledPlacefiles_.emplace(name);
UpdatePlacefileLayers();
}
else if (!enabled && enabledPlacefiles_.contains(name))
{
// Placefile disabled, remove layer
enabledPlacefiles_.erase(name);
RemovePlacefileLayer(name);
}
widget_->update();
});
connect(placefileManager_.get(),
&manager::PlacefileManager::PlacefileRemoved,
widget_,
[this](const std::string& name)
{
if (enabledPlacefiles_.contains(name))
{
// Placefile removed, remove layer
enabledPlacefiles_.erase(name);
RemovePlacefileLayer(name);
}
widget_->update();
});
connect(placefileManager_.get(),
&manager::PlacefileManager::PlacefileRenamed,
widget_,
[this](const std::string& oldName, const std::string& newName)
{
if (enabledPlacefiles_.contains(oldName))
{
// Remove old placefile layer
enabledPlacefiles_.erase(oldName);
RemovePlacefileLayer(oldName);
}
if (!enabledPlacefiles_.contains(newName) &&
placefileManager_->placefile_enabled(newName))
{
// Add new placefile layer
enabledPlacefiles_.emplace(newName);
UpdatePlacefileLayers();
}
widget_->update();
});
connect(placefileManager_.get(), connect(placefileManager_.get(),
&manager::PlacefileManager::PlacefileUpdated, &manager::PlacefileManager::PlacefileUpdated,
widget_, widget_,
[this]() { widget_->update(); }); [this]() { widget_->update(); });
// When the layer model changes, update the layers
connect(layerModel_.get(),
&QAbstractItemModel::dataChanged,
widget_,
[this](const QModelIndex& topLeft,
const QModelIndex& bottomRight,
const QList<int>& /* roles */)
{
static const int enabledColumn =
static_cast<int>(model::LayerModel::Column::Enabled);
const int displayColumn =
static_cast<int>(model::LayerModel::Column::DisplayMap1) +
static_cast<int>(id_);
// Update layers if the displayed or enabled state of the layer
// has changed
if ((topLeft.column() <= displayColumn &&
displayColumn <= bottomRight.column()) ||
(topLeft.column() <= enabledColumn &&
enabledColumn <= bottomRight.column()))
{
AddLayers();
}
});
connect(layerModel_.get(),
&QAbstractItemModel::modelReset,
widget_,
[this]() { AddLayers(); });
connect(layerModel_.get(),
&QAbstractItemModel::rowsInserted,
widget_,
[this](const QModelIndex& /* parent */, //
int /* first */,
int /* last */) { AddLayers(); });
connect(layerModel_.get(),
&QAbstractItemModel::rowsMoved,
widget_,
[this](const QModelIndex& /* sourceParent */,
int /* sourceStart */,
int /* sourceEnd */,
const QModelIndex& /* destinationParent */,
int /* destinationRow */) { AddLayers(); });
connect(layerModel_.get(),
&QAbstractItemModel::rowsRemoved,
widget_,
[this](const QModelIndex& /* parent */, //
int /* first */,
int /* last */) { AddLayers(); });
} }
common::Level3ProductCategoryMap MapWidget::GetAvailableLevel3Categories() common::Level3ProductCategoryMap MapWidget::GetAvailableLevel3Categories()
@ -756,7 +753,7 @@ void MapWidget::changeStyle()
void MapWidget::DumpLayerList() const void MapWidget::DumpLayerList() const
{ {
logger_->debug("Layers: {}", p->map_->layerIds().join(", ").toStdString()); logger_->info("Layers: {}", p->map_->layerIds().join(", ").toStdString());
} }
std::string MapWidgetImpl::FindMapSymbologyLayer() std::string MapWidgetImpl::FindMapSymbologyLayer()
@ -789,6 +786,12 @@ std::string MapWidgetImpl::FindMapSymbologyLayer()
void MapWidgetImpl::AddLayers() void MapWidgetImpl::AddLayers()
{ {
if (styleLayers_.isEmpty())
{
// Skip if the map has not yet been initialized
return;
}
logger_->debug("Add Layers"); logger_->debug("Add Layers");
// Clear custom layers // Clear custom layers
@ -855,7 +858,9 @@ void MapWidgetImpl::AddLayer(types::LayerType type,
else if (type == types::LayerType::Alert) else if (type == types::LayerType::Alert)
{ {
// Add the alert layer for the phenomenon // Add the alert layer for the phenomenon
alertLayer_->AddLayers(std::get<awips::Phenomenon>(description), before); auto newLayers = alertLayer_->AddLayers(
std::get<awips::Phenomenon>(description), before);
layerList_.insert(layerList_.end(), newLayers.cbegin(), newLayers.cend());
} }
else if (type == types::LayerType::Placefile) else if (type == types::LayerType::Placefile)
{ {
@ -904,6 +909,7 @@ void MapWidgetImpl::AddLayer(types::LayerType type,
radarProductView->range(), radarProductView->range(),
{radarSite->latitude(), radarSite->longitude()}, {radarSite->latitude(), radarSite->longitude()},
QString::fromStdString(before)); QString::fromStdString(before));
layerList_.push_back(types::GetLayerName(type, description));
} }
break; break;
@ -913,52 +919,6 @@ void MapWidgetImpl::AddLayer(types::LayerType type,
} }
} }
void MapWidgetImpl::RemovePlacefileLayer(const std::string& placefileName)
{
std::string layerName = GetPlacefileLayerName(placefileName);
// Remove layer from map
map_->removeLayer(layerName.c_str());
// Remove layer from internal layer list
auto layerIt = std::find(layerList_.begin(), layerList_.end(), layerName);
if (layerIt != layerList_.end())
{
layerList_.erase(layerIt);
}
// Determine if a layer exists for the placefile
auto placefileIt =
std::find_if(placefileLayers_.begin(),
placefileLayers_.end(),
[&placefileName](auto& layer)
{ return placefileName == layer->placefile_name(); });
if (placefileIt != placefileLayers_.end())
{
placefileLayers_.erase(placefileIt);
}
}
void MapWidgetImpl::UpdatePlacefileLayers()
{
// Loop through enabled placefiles
for (auto& placefileName : enabledPlacefiles_)
{
// Determine if a layer exists for the placefile
auto it = std::find_if(placefileLayers_.begin(),
placefileLayers_.end(),
[&placefileName](auto& layer) {
return placefileName == layer->placefile_name();
});
// If the layer doesn't exist, create it
if (it == placefileLayers_.end())
{
AddPlacefileLayer(placefileName);
}
}
}
void MapWidgetImpl::AddPlacefileLayer(const std::string& placefileName, void MapWidgetImpl::AddPlacefileLayer(const std::string& placefileName,
const std::string& before) const std::string& before)
{ {
@ -988,9 +948,16 @@ void MapWidgetImpl::AddLayer(const std::string& id,
std::unique_ptr<QMapLibreGL::CustomLayerHostInterface> pHost = std::unique_ptr<QMapLibreGL::CustomLayerHostInterface> pHost =
std::make_unique<LayerWrapper>(layer); std::make_unique<LayerWrapper>(layer);
try
{
map_->addCustomLayer(id.c_str(), std::move(pHost), before.c_str()); map_->addCustomLayer(id.c_str(), std::move(pHost), before.c_str());
layerList_.push_back(id); layerList_.push_back(id);
}
catch (const std::exception&)
{
// When dragging and dropping, a temporary duplicate layer exists
}
} }
void MapWidget::enterEvent(QEnterEvent* /* ev */) void MapWidget::enterEvent(QEnterEvent* /* ev */)

View file

@ -71,6 +71,10 @@ public:
~Impl() = default; ~Impl() = default;
void AddPlacefile(const std::string& name); void AddPlacefile(const std::string& name);
void HandlePlacefileRemoved(const std::string& name);
void HandlePlacefileRenamed(const std::string& oldName,
const std::string& newName);
void HandlePlacefileUpdate(const std::string& name, Column column);
void InitializeLayerSettings(); void InitializeLayerSettings();
void ReadLayerSettings(); void ReadLayerSettings();
void SynchronizePlacefileLayers(); void SynchronizePlacefileLayers();
@ -102,22 +106,26 @@ LayerModel::LayerModel(QObject* parent) :
connect(p->placefileManager_.get(), connect(p->placefileManager_.get(),
&manager::PlacefileManager::PlacefileEnabled, &manager::PlacefileManager::PlacefileEnabled,
this, this,
&LayerModel::HandlePlacefileUpdate); [this](const std::string& name, bool /* enabled */)
{ p->HandlePlacefileUpdate(name, Column::Enabled); });
connect(p->placefileManager_.get(), connect(p->placefileManager_.get(),
&manager::PlacefileManager::PlacefileRemoved, &manager::PlacefileManager::PlacefileRemoved,
this, this,
&LayerModel::HandlePlacefileRemoved); [this](const std::string& name)
{ p->HandlePlacefileRemoved(name); });
connect(p->placefileManager_.get(), connect(p->placefileManager_.get(),
&manager::PlacefileManager::PlacefileRenamed, &manager::PlacefileManager::PlacefileRenamed,
this, this,
&LayerModel::HandlePlacefileRenamed); [this](const std::string& oldName, const std::string& newName)
{ p->HandlePlacefileRenamed(oldName, newName); });
connect(p->placefileManager_.get(), connect(p->placefileManager_.get(),
&manager::PlacefileManager::PlacefileUpdated, &manager::PlacefileManager::PlacefileUpdated,
this, this,
&LayerModel::HandlePlacefileUpdate); [this](const std::string& name)
{ p->HandlePlacefileUpdate(name, Column::Description); });
p->InitializeLayerSettings(); p->InitializeLayerSettings();
p->ReadLayerSettings(); p->ReadLayerSettings();
@ -908,88 +916,92 @@ bool LayerModel::moveRows(const QModelIndex& sourceParent,
return moved; return moved;
} }
void LayerModel::HandlePlacefileRemoved(const std::string& name) void LayerModel::Impl::HandlePlacefileRemoved(const std::string& name)
{ {
auto it = auto it =
std::find_if(p->layers_.begin(), std::find_if(layers_.begin(),
p->layers_.end(), layers_.end(),
[&name](const auto& layer) [&name](const auto& layer)
{ {
return layer.type_ == types::LayerType::Placefile && return layer.type_ == types::LayerType::Placefile &&
std::get<std::string>(layer.description_) == name; std::get<std::string>(layer.description_) == name;
}); });
if (it != p->layers_.end()) if (it != layers_.end())
{ {
// Placefile exists, delete row // Placefile exists, delete row
const int row = std::distance(p->layers_.begin(), it); const int row = std::distance(layers_.begin(), it);
beginRemoveRows(QModelIndex(), row, row); self_->beginRemoveRows(QModelIndex(), row, row);
p->layers_.erase(it); layers_.erase(it);
endRemoveRows(); self_->endRemoveRows();
} }
} }
void LayerModel::HandlePlacefileRenamed(const std::string& oldName, void LayerModel::Impl::HandlePlacefileRenamed(const std::string& oldName,
const std::string& newName) const std::string& newName)
{ {
auto it = std::find_if( auto it = std::find_if(
p->layers_.begin(), layers_.begin(),
p->layers_.end(), layers_.end(),
[&oldName](const auto& layer) [&oldName](const auto& layer)
{ {
return layer.type_ == types::LayerType::Placefile && return layer.type_ == types::LayerType::Placefile &&
std::get<std::string>(layer.description_) == oldName; std::get<std::string>(layer.description_) == oldName;
}); });
if (it != p->layers_.end()) if (it != layers_.end())
{ {
// Placefile exists, mark row as updated // Placefile exists, mark row as updated
const int row = std::distance(p->layers_.begin(), it); const int row = std::distance(layers_.begin(), it);
QModelIndex topLeft = createIndex(row, kFirstColumn); QModelIndex topLeft =
QModelIndex bottomRight = createIndex(row, kLastColumn); self_->createIndex(row, static_cast<int>(Column::Description));
QModelIndex bottomRight =
self_->createIndex(row, static_cast<int>(Column::Description));
// Rename placefile // Rename placefile
it->description_ = newName; it->description_ = newName;
Q_EMIT dataChanged(topLeft, bottomRight); Q_EMIT self_->dataChanged(topLeft, bottomRight);
} }
else else
{ {
// Placefile doesn't exist, add row // Placefile doesn't exist, add row
p->AddPlacefile(newName); AddPlacefile(newName);
} }
} }
void LayerModel::HandlePlacefileUpdate(const std::string& name) void LayerModel::Impl::HandlePlacefileUpdate(const std::string& name,
Column column)
{ {
if (!p->placefilesInitialized_) if (!placefilesInitialized_)
{ {
p->initialPlacefiles_.push_back(name); initialPlacefiles_.push_back(name);
} }
auto it = auto it =
std::find_if(p->layers_.begin(), std::find_if(layers_.begin(),
p->layers_.end(), layers_.end(),
[&name](const auto& layer) [&name](const auto& layer)
{ {
return layer.type_ == types::LayerType::Placefile && return layer.type_ == types::LayerType::Placefile &&
std::get<std::string>(layer.description_) == name; std::get<std::string>(layer.description_) == name;
}); });
if (it != p->layers_.end()) if (it != layers_.end())
{ {
// Placefile exists, mark row as updated // Placefile exists, mark row as updated
const int row = std::distance(p->layers_.begin(), it); const int row = std::distance(layers_.begin(), it);
QModelIndex topLeft = createIndex(row, kFirstColumn); QModelIndex topLeft = self_->createIndex(row, static_cast<int>(column));
QModelIndex bottomRight = createIndex(row, kLastColumn); QModelIndex bottomRight =
self_->createIndex(row, static_cast<int>(column));
Q_EMIT dataChanged(topLeft, bottomRight); Q_EMIT self_->dataChanged(topLeft, bottomRight);
} }
else else
{ {
// Placefile doesn't exist, add row // Placefile doesn't exist, add row
p->AddPlacefile(name); AddPlacefile(name);
} }
} }

View file

@ -77,12 +77,6 @@ public:
static std::shared_ptr<LayerModel> Instance(); static std::shared_ptr<LayerModel> Instance();
public slots:
void HandlePlacefileRemoved(const std::string& name);
void HandlePlacefileRenamed(const std::string& oldName,
const std::string& newName);
void HandlePlacefileUpdate(const std::string& name);
private: private:
class Impl; class Impl;
std::unique_ptr<Impl> p; std::unique_ptr<Impl> p;