#include #include #include #include #include #include #include #include #include namespace scwx::qt::map { static const std::string logPrefix_ = "scwx::qt::map::marker_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class MarkerLayer::Impl { public: explicit Impl(MarkerLayer* self, const std::shared_ptr& glContext) : self_ {self}, geoIcons_ {std::make_shared(glContext)}, editMarkerDialog_ {std::make_shared()} { ConnectSignals(); } ~Impl() = default; Impl(const Impl&) = delete; Impl& operator=(const Impl&) = delete; Impl(const Impl&&) = delete; Impl& operator=(const Impl&&) = delete; void ReloadMarkers(); void ConnectSignals(); std::shared_ptr markerManager_ { manager::MarkerManager::Instance()}; void set_icon_sheets(); MarkerLayer* self_; std::shared_ptr geoIcons_; std::shared_ptr editMarkerDialog_; }; void MarkerLayer::Impl::ConnectSignals() { QObject::connect(markerManager_.get(), &manager::MarkerManager::MarkersUpdated, self_, [this]() { ReloadMarkers(); }); QObject::connect(markerManager_.get(), &manager::MarkerManager::IconsReady, self_, [this]() { set_icon_sheets(); }); QObject::connect(markerManager_.get(), &manager::MarkerManager::IconAdded, self_, [this]() { set_icon_sheets(); }); } void MarkerLayer::Impl::ReloadMarkers() { logger_->debug("ReloadMarkers()"); geoIcons_->StartIcons(); markerManager_->for_each( [this](const types::MarkerInfo& marker) { // must use local ID, instead of reference to marker in event handler // callback. const types::MarkerId id = marker.id; const std::shared_ptr icon = geoIcons_->AddIcon(); const std::string latitudeString = common::GetLatitudeString(marker.latitude); const std::string longitudeString = common::GetLongitudeString(marker.longitude); const std::string hoverText = marker.name != "" ? fmt::format( "{}\n{}, {}", marker.name, latitudeString, longitudeString) : fmt::format("{}, {}", latitudeString, longitudeString); auto iconInfo = markerManager_->get_icon(marker.iconName); if (iconInfo) { geoIcons_->SetIconTexture(icon, iconInfo->name, 0); } else { geoIcons_->SetIconTexture(icon, marker.iconName, 0); } geoIcons_->SetIconLocation(icon, marker.latitude, marker.longitude); geoIcons_->SetIconHoverText(icon, hoverText); geoIcons_->SetIconModulate(icon, marker.iconColor); geoIcons_->RegisterEventHandler( icon, [this, id](QEvent* ev) { switch (ev->type()) { case QEvent::Type::MouseButtonPress: { auto* mouseEvent = reinterpret_cast(ev); if (mouseEvent->buttons() == Qt::MouseButton::RightButton) { editMarkerDialog_->setup(id); editMarkerDialog_->show(); } } break; default: break; } }); }); geoIcons_->FinishIcons(); Q_EMIT self_->NeedsRendering(); } MarkerLayer::MarkerLayer(const std::shared_ptr& glContext) : DrawLayer(glContext, "MarkerLayer"), p(std::make_unique(this, glContext)) { AddDrawItem(p->geoIcons_); } MarkerLayer::~MarkerLayer() = default; void MarkerLayer::Initialize(const std::shared_ptr& mapContext) { logger_->debug("Initialize()"); DrawLayer::Initialize(mapContext); p->set_icon_sheets(); p->ReloadMarkers(); } void MarkerLayer::Impl::set_icon_sheets() { geoIcons_->StartIconSheets(); for (auto& markerIcon : markerManager_->get_icons()) { geoIcons_->AddIconSheet(markerIcon.second.name, 0, 0, markerIcon.second.hotX, markerIcon.second.hotY); } geoIcons_->FinishIconSheets(); } void MarkerLayer::Render(const std::shared_ptr& mapContext, const QMapLibre::CustomLayerRenderParameters& params) { gl::OpenGLFunctions& gl = gl_context()->gl(); DrawLayer::Render(mapContext, params); SCWX_GL_CHECK_ERROR(); } void MarkerLayer::Deinitialize() { logger_->debug("Deinitialize()"); DrawLayer::Deinitialize(); } } // namespace scwx::qt::map