From c2209908a0ddcff6a79f7d42fedf30e72e6975fe Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Wed, 2 Oct 2024 11:34:52 -0400 Subject: [PATCH 01/30] initial poi manager and types code --- .../source/scwx/qt/manager/poi_manager.cpp | 109 ++++++++++++++++++ .../source/scwx/qt/manager/poi_manager.hpp | 30 +++++ scwx-qt/source/scwx/qt/types/poi_types.hpp | 30 +++++ 3 files changed, 169 insertions(+) create mode 100644 scwx-qt/source/scwx/qt/manager/poi_manager.cpp create mode 100644 scwx-qt/source/scwx/qt/manager/poi_manager.hpp create mode 100644 scwx-qt/source/scwx/qt/types/poi_types.hpp diff --git a/scwx-qt/source/scwx/qt/manager/poi_manager.cpp b/scwx-qt/source/scwx/qt/manager/poi_manager.cpp new file mode 100644 index 00000000..658ae4da --- /dev/null +++ b/scwx-qt/source/scwx/qt/manager/poi_manager.cpp @@ -0,0 +1,109 @@ +#include +#include +#include + +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace manager +{ + +static const std::string logPrefix_ = "scwx::qt::manager::placefile_manager"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + +static const std::string kNameName_ = "name"; +static const std::string kLatitudeName_ = "latitude"; +static const std::string kLongitudeName_ = "longitude"; + +class POIManager::Impl +{ +public: + class PointOfInterest; + + explicit Impl(POIManager* self) : self_ {self} {} + + std::string poiSettingsPath_ {}; + + POIManager* self_; + + void ReadPOISettings(); + +}; + +class POIManager::Impl::PointOfInterest +{ +public: + PointOfInterest(std::string name, double latitude, double longitude) : + name_ {name}, latitude_ {latitude}, longitude_ {longitude} + { + } + + std::string name_; + double latitude_; + double longitude_; + + friend void tag_invoke(boost::json::value_from_tag, + boost::json::value& jv, + const std::shared_ptr& record) + { + jv = {{kNameName_, record->name_}, + {kLatitudeName_, record->latitude_}, + {kLongitudeName_, record->longitude_}}; + } + + friend PointOfInterest tag_invoke(boost::json::value_to_tag, + const boost::json::value& jv) + { + return PointOfInterest( + boost::json::value_to(jv.at(kNameName_)), + boost::json::value_to(jv.at(kLatitudeName_)), + boost::json::value_to(jv.at(kLongitudeName_))); + } +}; + +POIManager::POIManager() : p(std::make_unique(this)) {} + +void POIManager::Impl::ReadPOISettings() +{ + logger_->info("Reading point of intrest settings"); + + boost::json::value poiJson = nullptr; + + // Determine if poi settings exists + if (std::filesystem::exists(poiSettingsPath_)) + { + poiJson = util::json::ReadJsonFile(poiSettingsPath_); + } + + if (poiJson != nullptr && poiJson.is_array()) + { + // For each poi entry + auto& poiArray = poiJson.as_array(); + for (auto& poiEntry : poiArray) + { + try + { + PointOfInterest record = + boost::json::value_to(poiEntry); + + if (!record.name_.empty()) + { + // Add record + } + } + catch (const std::exception& ex) + { + logger_->warn("Invalid point of interest entry: {}", ex.what()); + } + } + } +} + +} // namespace manager +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/manager/poi_manager.hpp b/scwx-qt/source/scwx/qt/manager/poi_manager.hpp new file mode 100644 index 00000000..b0bc574d --- /dev/null +++ b/scwx-qt/source/scwx/qt/manager/poi_manager.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace manager +{ + +class POIManager : public QObject +{ + Q_OBJECT + +public: + explicit POIManager(); + ~POIManager(); + + +private: + class Impl; + std::unique_ptr p; +}; + +} // namespace manager +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/types/poi_types.hpp b/scwx-qt/source/scwx/qt/types/poi_types.hpp new file mode 100644 index 00000000..922ea364 --- /dev/null +++ b/scwx-qt/source/scwx/qt/types/poi_types.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include + +namespace scwx +{ +namespace qt +{ +namespace types +{ + +struct PointOfInterest +{ + PointOfInterest(std::string name, + double latitude, + double longitude) : + name_ {name}, + latitude_ {latitude}, + longitude_ {longitude} + { + } + + std::string name_; + double latitude_; + double longitude_; +}; + +} // namespace types +} // namespace qt +} // namespace scwx From ec4387112ebb81a6d542056b86e4826574cb4042 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Fri, 4 Oct 2024 16:40:56 -0400 Subject: [PATCH 02/30] Add poi layer --- scwx-qt/source/scwx/qt/map/poi_layer.cpp | 97 ++++++++++++++++++++ scwx-qt/source/scwx/qt/map/poi_layer.hpp | 33 +++++++ scwx-qt/source/scwx/qt/types/layer_types.cpp | 1 + scwx-qt/source/scwx/qt/types/layer_types.hpp | 1 + 4 files changed, 132 insertions(+) create mode 100644 scwx-qt/source/scwx/qt/map/poi_layer.cpp create mode 100644 scwx-qt/source/scwx/qt/map/poi_layer.hpp diff --git a/scwx-qt/source/scwx/qt/map/poi_layer.cpp b/scwx-qt/source/scwx/qt/map/poi_layer.cpp new file mode 100644 index 00000000..a1b0e630 --- /dev/null +++ b/scwx-qt/source/scwx/qt/map/poi_layer.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include + +namespace scwx +{ +namespace qt +{ +namespace map +{ + +static const std::string logPrefix_ = "scwx::qt::map::poi_layer"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + + +class POILayer::Impl +{ +public: + explicit Impl(std::shared_ptr context) : + geoIcons_ {std::make_shared(context)} + { + } + ~Impl() {} + + void ReloadPOIs(); + + const std::string& poiIconName_ { + types::GetTextureName(types::ImageTexture::Crosshairs24)}; + + std::shared_ptr geoIcons_; +}; + +void POILayer::Impl::ReloadPOIs() +{ + logger_->debug("ReloadPOIs"); + auto poiManager = manager::POIManager::Instance(); + + geoIcons_->StartIcons(); + + for (size_t i = 0; i < poiManager->poi_count(); i++) + { + types::PointOfInterest poi = poiManager->get_poi(i); + std::shared_ptr icon = geoIcons_->AddIcon(); + geoIcons_->SetIconTexture(icon, poiIconName_, 0); + geoIcons_->SetIconLocation(icon, poi.latitude_, poi.longitude_); + } + + geoIcons_->FinishIcons(); +} + +POILayer::POILayer(const std::shared_ptr& context) : + DrawLayer(context), + p(std::make_unique(context)) +{ + AddDrawItem(p->geoIcons_); +} + +POILayer::~POILayer() = default; + +void POILayer::Initialize() +{ + logger_->debug("Initialize()"); + DrawLayer::Initialize(); + + p->geoIcons_->StartIconSheets(); + p->geoIcons_->AddIconSheet(p->poiIconName_); + p->geoIcons_->FinishIconSheets(); +} + +void POILayer::Render( + const QMapLibre::CustomLayerRenderParameters& params) +{ + //auto poiManager = manager::POIManager::Instance(); + gl::OpenGLFunctions& gl = context()->gl(); + + // TODO. do not redo this every time + p->ReloadPOIs(); + + DrawLayer::Render(params); + + SCWX_GL_CHECK_ERROR(); +} + +void POILayer::Deinitialize() +{ + logger_->debug("Deinitialize()"); + + DrawLayer::Deinitialize(); +} + +} // namespace map +} // namespace qt +} // namespace scwx + diff --git a/scwx-qt/source/scwx/qt/map/poi_layer.hpp b/scwx-qt/source/scwx/qt/map/poi_layer.hpp new file mode 100644 index 00000000..5bc12660 --- /dev/null +++ b/scwx-qt/source/scwx/qt/map/poi_layer.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace map +{ + +class POILayer : public DrawLayer +{ + Q_OBJECT + +public: + explicit POILayer(const std::shared_ptr& context); + ~POILayer(); + + void Initialize() override final; + void Render(const QMapLibre::CustomLayerRenderParameters&) override final; + void Deinitialize() override final; + +private: + class Impl; + std::unique_ptr p; +}; + +} // namespace map +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/types/layer_types.cpp b/scwx-qt/source/scwx/qt/types/layer_types.cpp index 6e66c5d1..3ab775e3 100644 --- a/scwx-qt/source/scwx/qt/types/layer_types.cpp +++ b/scwx-qt/source/scwx/qt/types/layer_types.cpp @@ -31,6 +31,7 @@ static const std::unordered_map informationLayerName_ {{InformationLayer::MapOverlay, "Map Overlay"}, {InformationLayer::RadarSite, "Radar Sites"}, {InformationLayer::ColorTable, "Color Table"}, + {InformationLayer::POILayer, "Point of Interest"}, {InformationLayer::Unknown, "?"}}; static const std::unordered_map mapLayerName_ { diff --git a/scwx-qt/source/scwx/qt/types/layer_types.hpp b/scwx-qt/source/scwx/qt/types/layer_types.hpp index f0561a6e..04a4aef9 100644 --- a/scwx-qt/source/scwx/qt/types/layer_types.hpp +++ b/scwx-qt/source/scwx/qt/types/layer_types.hpp @@ -44,6 +44,7 @@ enum class InformationLayer MapOverlay, RadarSite, ColorTable, + POILayer, Unknown }; From f5d867cf1aef5b2d91a1620bdc9dbad0834f4c89 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Fri, 4 Oct 2024 16:42:54 -0400 Subject: [PATCH 03/30] Add working poi manager implementation --- .../source/scwx/qt/manager/poi_manager.cpp | 193 ++++++++++++++++-- .../source/scwx/qt/manager/poi_manager.hpp | 11 + 2 files changed, 191 insertions(+), 13 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/poi_manager.cpp b/scwx-qt/source/scwx/qt/manager/poi_manager.cpp index 658ae4da..9124bed4 100644 --- a/scwx-qt/source/scwx/qt/manager/poi_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/poi_manager.cpp @@ -1,9 +1,14 @@ #include -#include +#include #include +#include +#include #include +#include +#include +#include #include namespace scwx @@ -13,7 +18,7 @@ namespace qt namespace manager { -static const std::string logPrefix_ = "scwx::qt::manager::placefile_manager"; +static const std::string logPrefix_ = "scwx::qt::manager::poi_manager"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static const std::string kNameName_ = "name"; @@ -23,22 +28,27 @@ static const std::string kLongitudeName_ = "longitude"; class POIManager::Impl { public: - class PointOfInterest; + class POIRecord; explicit Impl(POIManager* self) : self_ {self} {} + ~Impl() {} std::string poiSettingsPath_ {}; + std::vector> poiRecords_ {}; POIManager* self_; + void InitializePOISettings(); void ReadPOISettings(); + void WritePOISettings(); + std::shared_ptr GetPOIByName(const std::string& name); }; -class POIManager::Impl::PointOfInterest +class POIManager::Impl::POIRecord { public: - PointOfInterest(std::string name, double latitude, double longitude) : + POIRecord(std::string name, double latitude, double longitude) : name_ {name}, latitude_ {latitude}, longitude_ {longitude} { } @@ -49,28 +59,45 @@ public: friend void tag_invoke(boost::json::value_from_tag, boost::json::value& jv, - const std::shared_ptr& record) + const std::shared_ptr& record) { jv = {{kNameName_, record->name_}, {kLatitudeName_, record->latitude_}, {kLongitudeName_, record->longitude_}}; } - friend PointOfInterest tag_invoke(boost::json::value_to_tag, + friend POIRecord tag_invoke(boost::json::value_to_tag, const boost::json::value& jv) { - return PointOfInterest( + return POIRecord( boost::json::value_to(jv.at(kNameName_)), boost::json::value_to(jv.at(kLatitudeName_)), boost::json::value_to(jv.at(kLongitudeName_))); } }; -POIManager::POIManager() : p(std::make_unique(this)) {} + +void POIManager::Impl::InitializePOISettings() +{ + std::string appDataPath { + QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + .toStdString()}; + + if (!std::filesystem::exists(appDataPath)) + { + if (!std::filesystem::create_directories(appDataPath)) + { + logger_->error("Unable to create application data directory: \"{}\"", + appDataPath); + } + } + + poiSettingsPath_ = appDataPath + "/points_of_interest.json"; +} void POIManager::Impl::ReadPOISettings() { - logger_->info("Reading point of intrest settings"); + logger_->info("Reading point of interest settings"); boost::json::value poiJson = nullptr; @@ -84,16 +111,18 @@ void POIManager::Impl::ReadPOISettings() { // For each poi entry auto& poiArray = poiJson.as_array(); + poiRecords_.reserve(poiArray.size()); for (auto& poiEntry : poiArray) { try { - PointOfInterest record = - boost::json::value_to(poiEntry); + POIRecord record = + boost::json::value_to(poiEntry); if (!record.name_.empty()) { - // Add record + poiRecords_.emplace_back(std::make_shared( + record.name_, record.latitude_, record.longitude_)); } } catch (const std::exception& ex) @@ -101,9 +130,147 @@ void POIManager::Impl::ReadPOISettings() logger_->warn("Invalid point of interest entry: {}", ex.what()); } } + + logger_->debug("{} point of interest entries", poiRecords_.size()); } } +void POIManager::Impl::WritePOISettings() +{ + logger_->info("Saving point of interest settings"); + + auto poiJson = boost::json::value_from(poiRecords_); + util::json::WriteJsonFile(poiSettingsPath_, poiJson); +} + +std::shared_ptr +POIManager::Impl::GetPOIByName(const std::string& name) +{ + for (auto& poiRecord : poiRecords_) + { + if (poiRecord->name_ == name) + { + return poiRecord; + } + } + + return nullptr; +} + +POIManager::POIManager() : p(std::make_unique(this)) +{ + // TODO THREADING? + try + { + p->InitializePOISettings(); + + // Read POI settings on startup + //main::Application::WaitForInitialization(); + p->ReadPOISettings(); + } + catch (const std::exception& ex) + { + logger_->error(ex.what()); + } +} + +POIManager::~POIManager() +{ + p->WritePOISettings(); +} + +size_t POIManager::poi_count() +{ + return p->poiRecords_.size(); +} + +// TODO deal with out of range/not found +types::PointOfInterest POIManager::get_poi(size_t index) +{ + std::shared_ptr poiRecord = + p->poiRecords_[index]; + return types::PointOfInterest( + poiRecord->name_, poiRecord->latitude_, poiRecord->longitude_); +} + +types::PointOfInterest POIManager::get_poi(const std::string& name) +{ + std::shared_ptr poiRecord = + p->GetPOIByName(name); + return types::PointOfInterest( + poiRecord->name_, poiRecord->latitude_, poiRecord->longitude_); +} + +void POIManager::set_poi(size_t index, const types::PointOfInterest& poi) +{ + std::shared_ptr poiRecord = + p->poiRecords_[index]; + poiRecord->name_ = poi.name_; + poiRecord->latitude_ = poi.latitude_; + poiRecord->longitude_ = poi.longitude_; +} + +void POIManager::set_poi(const std::string& name, + const types::PointOfInterest& poi) +{ + std::shared_ptr poiRecord = + p->GetPOIByName(name); + poiRecord->name_ = poi.name_; + poiRecord->latitude_ = poi.latitude_; + poiRecord->longitude_ = poi.longitude_; +} + +void POIManager::add_poi(const types::PointOfInterest& poi) +{ + p->poiRecords_.emplace_back(std::make_shared( + poi.name_, poi.latitude_, poi.longitude_)); +} + +void POIManager::move_poi(size_t from, size_t to) +{ + if (from >= p->poiRecords_.size() || to >= p->poiRecords_.size()) + { + return; + } + std::shared_ptr poiRecord = + p->poiRecords_[from]; + + if (from == to) + { + } + else if (from < to) + { + for (size_t i = from; i < to; i++) + { + p->poiRecords_[i] = p->poiRecords_[i + 1]; + } + p->poiRecords_[to] = poiRecord; + } + else + { + for (size_t i = from; i > to; i--) + { + p->poiRecords_[i] = p->poiRecords_[i - 1]; + } + p->poiRecords_[to] = poiRecord; + } +} + +std::shared_ptr POIManager::Instance() +{ + static std::weak_ptr poiManagerReference_ {}; + + std::shared_ptr poiManager = poiManagerReference_.lock(); + + if (poiManager == nullptr) + { + poiManager = std::make_shared(); + poiManagerReference_ = poiManager; + } + + return poiManager; +} + } // namespace manager } // namespace qt } // namespace scwx diff --git a/scwx-qt/source/scwx/qt/manager/poi_manager.hpp b/scwx-qt/source/scwx/qt/manager/poi_manager.hpp index b0bc574d..63144cc8 100644 --- a/scwx-qt/source/scwx/qt/manager/poi_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/poi_manager.hpp @@ -2,6 +2,8 @@ #include +#include + #include namespace scwx @@ -19,6 +21,15 @@ public: explicit POIManager(); ~POIManager(); + size_t poi_count(); + types::PointOfInterest get_poi(size_t index); + types::PointOfInterest get_poi(const std::string& name); + void set_poi(size_t index, const types::PointOfInterest& poi); + void set_poi(const std::string& name, const types::PointOfInterest& poi); + void add_poi(const types::PointOfInterest& poi); + void move_poi(size_t from, size_t to); + + static std::shared_ptr Instance(); private: class Impl; From 0a0989e5f43701250d819a122a170d430bac87c5 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Fri, 4 Oct 2024 16:43:40 -0400 Subject: [PATCH 04/30] Do initial work to get layer rendering --- scwx-qt/scwx-qt.cmake | 5 +++++ scwx-qt/source/scwx/qt/main/main_window.cpp | 3 +++ scwx-qt/source/scwx/qt/map/map_widget.cpp | 9 +++++++++ scwx-qt/source/scwx/qt/model/layer_model.cpp | 1 + 4 files changed, 18 insertions(+) diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 06646bbe..01ff239e 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -95,6 +95,7 @@ set(HDR_MANAGER source/scwx/qt/manager/alert_manager.hpp source/scwx/qt/manager/log_manager.hpp source/scwx/qt/manager/media_manager.hpp source/scwx/qt/manager/placefile_manager.hpp + source/scwx/qt/manager/poi_manager.hpp source/scwx/qt/manager/position_manager.hpp source/scwx/qt/manager/radar_product_manager.hpp source/scwx/qt/manager/radar_product_manager_notifier.hpp @@ -111,6 +112,7 @@ set(SRC_MANAGER source/scwx/qt/manager/alert_manager.cpp source/scwx/qt/manager/log_manager.cpp source/scwx/qt/manager/media_manager.cpp source/scwx/qt/manager/placefile_manager.cpp + source/scwx/qt/manager/poi_manager.cpp source/scwx/qt/manager/position_manager.cpp source/scwx/qt/manager/radar_product_manager.cpp source/scwx/qt/manager/radar_product_manager_notifier.cpp @@ -132,6 +134,7 @@ set(HDR_MAP source/scwx/qt/map/alert_layer.hpp source/scwx/qt/map/overlay_layer.hpp source/scwx/qt/map/overlay_product_layer.hpp source/scwx/qt/map/placefile_layer.hpp + source/scwx/qt/map/poi_layer.hpp source/scwx/qt/map/radar_product_layer.hpp source/scwx/qt/map/radar_range_layer.hpp source/scwx/qt/map/radar_site_layer.hpp) @@ -146,6 +149,7 @@ set(SRC_MAP source/scwx/qt/map/alert_layer.cpp source/scwx/qt/map/overlay_layer.cpp source/scwx/qt/map/overlay_product_layer.cpp source/scwx/qt/map/placefile_layer.cpp + source/scwx/qt/map/poi_layer.cpp source/scwx/qt/map/radar_product_layer.cpp source/scwx/qt/map/radar_range_layer.cpp source/scwx/qt/map/radar_site_layer.cpp) @@ -215,6 +219,7 @@ set(HDR_TYPES source/scwx/qt/types/alert_types.hpp source/scwx/qt/types/location_types.hpp source/scwx/qt/types/map_types.hpp source/scwx/qt/types/media_types.hpp + source/scwx/qt/types/poi_types.hpp source/scwx/qt/types/qt_types.hpp source/scwx/qt/types/radar_product_record.hpp source/scwx/qt/types/text_event_key.hpp diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index cadd9c90..77c130a4 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -91,6 +92,7 @@ public: updateDialog_ {nullptr}, alertManager_ {manager::AlertManager::Instance()}, placefileManager_ {manager::PlacefileManager::Instance()}, + poiManager_ {manager::POIManager::Instance()}, positionManager_ {manager::PositionManager::Instance()}, textEventManager_ {manager::TextEventManager::Instance()}, timelineManager_ {manager::TimelineManager::Instance()}, @@ -217,6 +219,7 @@ public: std::shared_ptr hotkeyManager_ { manager::HotkeyManager::Instance()}; std::shared_ptr placefileManager_; + std::shared_ptr poiManager_; std::shared_ptr positionManager_; std::shared_ptr textEventManager_; std::shared_ptr timelineManager_; diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index e718bc0e..4837f387 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -81,6 +82,7 @@ public: radarProductLayer_ {nullptr}, overlayLayer_ {nullptr}, placefileLayer_ {nullptr}, + poiLayer_ {nullptr}, colorTableLayer_ {nullptr}, autoRefreshEnabled_ {true}, autoUpdateEnabled_ {true}, @@ -223,6 +225,7 @@ public: std::shared_ptr overlayLayer_; std::shared_ptr overlayProductLayer_ {nullptr}; std::shared_ptr placefileLayer_; + std::shared_ptr poiLayer_; std::shared_ptr colorTableLayer_; std::shared_ptr radarSiteLayer_ {nullptr}; @@ -1232,6 +1235,12 @@ void MapWidgetImpl::AddLayer(types::LayerType type, { widget_->RadarSiteRequested(id); }); break; + // Create the radar site layer + case types::InformationLayer::POILayer: + poiLayer_ = std::make_shared(context_); + AddLayer(layerName, poiLayer_, before); + break; + default: break; } diff --git a/scwx-qt/source/scwx/qt/model/layer_model.cpp b/scwx-qt/source/scwx/qt/model/layer_model.cpp index 999a2de9..fbc565b5 100644 --- a/scwx-qt/source/scwx/qt/model/layer_model.cpp +++ b/scwx-qt/source/scwx/qt/model/layer_model.cpp @@ -43,6 +43,7 @@ static const std::vector kDefaultLayers_ { types::InformationLayer::RadarSite, false, {false, false, false, false}}, + {types::LayerType::Information, types::InformationLayer::POILayer, true}, {types::LayerType::Data, types::DataLayer::RadarRange, true}, {types::LayerType::Alert, awips::Phenomenon::Tornado, true}, {types::LayerType::Alert, awips::Phenomenon::SnowSquall, true}, From 27828943f425d4e2973066bcd97abc63abe47c7e Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Fri, 4 Oct 2024 19:02:04 -0400 Subject: [PATCH 05/30] change texture for marker and remove unneeded logging --- scwx-qt/source/scwx/qt/map/poi_layer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scwx-qt/source/scwx/qt/map/poi_layer.cpp b/scwx-qt/source/scwx/qt/map/poi_layer.cpp index a1b0e630..4bfb4338 100644 --- a/scwx-qt/source/scwx/qt/map/poi_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/poi_layer.cpp @@ -28,14 +28,13 @@ public: void ReloadPOIs(); const std::string& poiIconName_ { - types::GetTextureName(types::ImageTexture::Crosshairs24)}; + types::GetTextureName(types::ImageTexture::Cursor17)}; std::shared_ptr geoIcons_; }; void POILayer::Impl::ReloadPOIs() { - logger_->debug("ReloadPOIs"); auto poiManager = manager::POIManager::Instance(); geoIcons_->StartIcons(); From da271c326a660fbd7034484a926bf87046fb2abd Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Fri, 4 Oct 2024 19:05:37 -0400 Subject: [PATCH 06/30] rename files to marker instead of poi --- .../scwx/qt/manager/{poi_manager.cpp => marker_manager.cpp} | 0 .../scwx/qt/manager/{poi_manager.hpp => marker_manager.hpp} | 0 scwx-qt/source/scwx/qt/types/{poi_types.hpp => marker_types.hpp} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename scwx-qt/source/scwx/qt/manager/{poi_manager.cpp => marker_manager.cpp} (100%) rename scwx-qt/source/scwx/qt/manager/{poi_manager.hpp => marker_manager.hpp} (100%) rename scwx-qt/source/scwx/qt/types/{poi_types.hpp => marker_types.hpp} (100%) diff --git a/scwx-qt/source/scwx/qt/manager/poi_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp similarity index 100% rename from scwx-qt/source/scwx/qt/manager/poi_manager.cpp rename to scwx-qt/source/scwx/qt/manager/marker_manager.cpp diff --git a/scwx-qt/source/scwx/qt/manager/poi_manager.hpp b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp similarity index 100% rename from scwx-qt/source/scwx/qt/manager/poi_manager.hpp rename to scwx-qt/source/scwx/qt/manager/marker_manager.hpp diff --git a/scwx-qt/source/scwx/qt/types/poi_types.hpp b/scwx-qt/source/scwx/qt/types/marker_types.hpp similarity index 100% rename from scwx-qt/source/scwx/qt/types/poi_types.hpp rename to scwx-qt/source/scwx/qt/types/marker_types.hpp From cd169026354806c4bdde7d81899d0b5641984103 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Fri, 4 Oct 2024 19:10:34 -0400 Subject: [PATCH 07/30] rename another file to marker fro poi --- scwx-qt/source/scwx/qt/map/{poi_layer.cpp => marker_layer.cpp} | 0 scwx-qt/source/scwx/qt/map/{poi_layer.hpp => marker_layer.hpp} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename scwx-qt/source/scwx/qt/map/{poi_layer.cpp => marker_layer.cpp} (100%) rename scwx-qt/source/scwx/qt/map/{poi_layer.hpp => marker_layer.hpp} (100%) diff --git a/scwx-qt/source/scwx/qt/map/poi_layer.cpp b/scwx-qt/source/scwx/qt/map/marker_layer.cpp similarity index 100% rename from scwx-qt/source/scwx/qt/map/poi_layer.cpp rename to scwx-qt/source/scwx/qt/map/marker_layer.cpp diff --git a/scwx-qt/source/scwx/qt/map/poi_layer.hpp b/scwx-qt/source/scwx/qt/map/marker_layer.hpp similarity index 100% rename from scwx-qt/source/scwx/qt/map/poi_layer.hpp rename to scwx-qt/source/scwx/qt/map/marker_layer.hpp From 31940441edd9444ca1e5cbaf48944bda3464c17b Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Fri, 4 Oct 2024 19:31:47 -0400 Subject: [PATCH 08/30] renamed all POI/point of intrest to marker --- scwx-qt/scwx-qt.cmake | 10 +- scwx-qt/source/scwx/qt/main/main_window.cpp | 6 +- .../source/scwx/qt/manager/marker_manager.cpp | 188 +++++++++--------- .../source/scwx/qt/manager/marker_manager.hpp | 24 +-- scwx-qt/source/scwx/qt/map/map_widget.cpp | 12 +- scwx-qt/source/scwx/qt/map/marker_layer.cpp | 44 ++-- scwx-qt/source/scwx/qt/map/marker_layer.hpp | 6 +- scwx-qt/source/scwx/qt/model/layer_model.cpp | 2 +- scwx-qt/source/scwx/qt/types/layer_types.cpp | 2 +- scwx-qt/source/scwx/qt/types/layer_types.hpp | 2 +- scwx-qt/source/scwx/qt/types/marker_types.hpp | 14 +- 11 files changed, 153 insertions(+), 157 deletions(-) diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 01ff239e..6edb022d 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -95,7 +95,7 @@ set(HDR_MANAGER source/scwx/qt/manager/alert_manager.hpp source/scwx/qt/manager/log_manager.hpp source/scwx/qt/manager/media_manager.hpp source/scwx/qt/manager/placefile_manager.hpp - source/scwx/qt/manager/poi_manager.hpp + source/scwx/qt/manager/marker_manager.hpp source/scwx/qt/manager/position_manager.hpp source/scwx/qt/manager/radar_product_manager.hpp source/scwx/qt/manager/radar_product_manager_notifier.hpp @@ -112,7 +112,7 @@ set(SRC_MANAGER source/scwx/qt/manager/alert_manager.cpp source/scwx/qt/manager/log_manager.cpp source/scwx/qt/manager/media_manager.cpp source/scwx/qt/manager/placefile_manager.cpp - source/scwx/qt/manager/poi_manager.cpp + source/scwx/qt/manager/marker_manager.cpp source/scwx/qt/manager/position_manager.cpp source/scwx/qt/manager/radar_product_manager.cpp source/scwx/qt/manager/radar_product_manager_notifier.cpp @@ -134,7 +134,7 @@ set(HDR_MAP source/scwx/qt/map/alert_layer.hpp source/scwx/qt/map/overlay_layer.hpp source/scwx/qt/map/overlay_product_layer.hpp source/scwx/qt/map/placefile_layer.hpp - source/scwx/qt/map/poi_layer.hpp + source/scwx/qt/map/marker_layer.hpp source/scwx/qt/map/radar_product_layer.hpp source/scwx/qt/map/radar_range_layer.hpp source/scwx/qt/map/radar_site_layer.hpp) @@ -149,7 +149,7 @@ set(SRC_MAP source/scwx/qt/map/alert_layer.cpp source/scwx/qt/map/overlay_layer.cpp source/scwx/qt/map/overlay_product_layer.cpp source/scwx/qt/map/placefile_layer.cpp - source/scwx/qt/map/poi_layer.cpp + source/scwx/qt/map/marker_layer.cpp source/scwx/qt/map/radar_product_layer.cpp source/scwx/qt/map/radar_range_layer.cpp source/scwx/qt/map/radar_site_layer.cpp) @@ -219,7 +219,7 @@ set(HDR_TYPES source/scwx/qt/types/alert_types.hpp source/scwx/qt/types/location_types.hpp source/scwx/qt/types/map_types.hpp source/scwx/qt/types/media_types.hpp - source/scwx/qt/types/poi_types.hpp + source/scwx/qt/types/marker_types.hpp source/scwx/qt/types/qt_types.hpp source/scwx/qt/types/radar_product_record.hpp source/scwx/qt/types/text_event_key.hpp diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index 77c130a4..836d6784 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include #include @@ -92,7 +92,7 @@ public: updateDialog_ {nullptr}, alertManager_ {manager::AlertManager::Instance()}, placefileManager_ {manager::PlacefileManager::Instance()}, - poiManager_ {manager::POIManager::Instance()}, + markerManager_ {manager::MarkerManager::Instance()}, positionManager_ {manager::PositionManager::Instance()}, textEventManager_ {manager::TextEventManager::Instance()}, timelineManager_ {manager::TimelineManager::Instance()}, @@ -219,7 +219,7 @@ public: std::shared_ptr hotkeyManager_ { manager::HotkeyManager::Instance()}; std::shared_ptr placefileManager_; - std::shared_ptr poiManager_; + std::shared_ptr markerManager_; std::shared_ptr positionManager_; std::shared_ptr textEventManager_; std::shared_ptr timelineManager_; diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp index 9124bed4..15e8f044 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp @@ -1,5 +1,5 @@ -#include -#include +#include +#include #include #include #include @@ -18,37 +18,37 @@ namespace qt namespace manager { -static const std::string logPrefix_ = "scwx::qt::manager::poi_manager"; +static const std::string logPrefix_ = "scwx::qt::manager::marker_manager"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static const std::string kNameName_ = "name"; static const std::string kLatitudeName_ = "latitude"; static const std::string kLongitudeName_ = "longitude"; -class POIManager::Impl +class MarkerManager::Impl { public: - class POIRecord; + class MarkerRecord; - explicit Impl(POIManager* self) : self_ {self} {} + explicit Impl(MarkerManager* self) : self_ {self} {} ~Impl() {} - std::string poiSettingsPath_ {}; - std::vector> poiRecords_ {}; + std::string markerSettingsPath_ {}; + std::vector> markerRecords_ {}; - POIManager* self_; + MarkerManager* self_; - void InitializePOISettings(); - void ReadPOISettings(); - void WritePOISettings(); - std::shared_ptr GetPOIByName(const std::string& name); + void InitializeMarkerSettings(); + void ReadMarkerSettings(); + void WriteMarkerSettings(); + std::shared_ptr GetMarkerByName(const std::string& name); }; -class POIManager::Impl::POIRecord +class MarkerManager::Impl::MarkerRecord { public: - POIRecord(std::string name, double latitude, double longitude) : + MarkerRecord(std::string name, double latitude, double longitude) : name_ {name}, latitude_ {latitude}, longitude_ {longitude} { } @@ -59,17 +59,17 @@ public: friend void tag_invoke(boost::json::value_from_tag, boost::json::value& jv, - const std::shared_ptr& record) + const std::shared_ptr& record) { jv = {{kNameName_, record->name_}, {kLatitudeName_, record->latitude_}, {kLongitudeName_, record->longitude_}}; } - friend POIRecord tag_invoke(boost::json::value_to_tag, + friend MarkerRecord tag_invoke(boost::json::value_to_tag, const boost::json::value& jv) { - return POIRecord( + return MarkerRecord( boost::json::value_to(jv.at(kNameName_)), boost::json::value_to(jv.at(kLatitudeName_)), boost::json::value_to(jv.at(kLongitudeName_))); @@ -77,7 +77,7 @@ public: }; -void POIManager::Impl::InitializePOISettings() +void MarkerManager::Impl::InitializeMarkerSettings() { std::string appDataPath { QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) @@ -92,81 +92,81 @@ void POIManager::Impl::InitializePOISettings() } } - poiSettingsPath_ = appDataPath + "/points_of_interest.json"; + markerSettingsPath_ = appDataPath + "/location-markers.json"; } -void POIManager::Impl::ReadPOISettings() +void MarkerManager::Impl::ReadMarkerSettings() { - logger_->info("Reading point of interest settings"); + logger_->info("Reading location marker settings"); - boost::json::value poiJson = nullptr; + boost::json::value markerJson = nullptr; - // Determine if poi settings exists - if (std::filesystem::exists(poiSettingsPath_)) + // Determine if marker settings exists + if (std::filesystem::exists(markerSettingsPath_)) { - poiJson = util::json::ReadJsonFile(poiSettingsPath_); + markerJson = util::json::ReadJsonFile(markerSettingsPath_); } - if (poiJson != nullptr && poiJson.is_array()) + if (markerJson != nullptr && markerJson.is_array()) { - // For each poi entry - auto& poiArray = poiJson.as_array(); - poiRecords_.reserve(poiArray.size()); - for (auto& poiEntry : poiArray) + // For each marker entry + auto& markerArray = markerJson.as_array(); + markerRecords_.reserve(markerArray.size()); + for (auto& markerEntry : markerArray) { try { - POIRecord record = - boost::json::value_to(poiEntry); + MarkerRecord record = + boost::json::value_to(markerEntry); if (!record.name_.empty()) { - poiRecords_.emplace_back(std::make_shared( + markerRecords_.emplace_back(std::make_shared( record.name_, record.latitude_, record.longitude_)); } } catch (const std::exception& ex) { - logger_->warn("Invalid point of interest entry: {}", ex.what()); + logger_->warn("Invalid location marker entry: {}", ex.what()); } } - logger_->debug("{} point of interest entries", poiRecords_.size()); + logger_->debug("{} location marker entries", markerRecords_.size()); } } -void POIManager::Impl::WritePOISettings() +void MarkerManager::Impl::WriteMarkerSettings() { - logger_->info("Saving point of interest settings"); + logger_->info("Saving location marker settings"); - auto poiJson = boost::json::value_from(poiRecords_); - util::json::WriteJsonFile(poiSettingsPath_, poiJson); + auto markerJson = boost::json::value_from(markerRecords_); + util::json::WriteJsonFile(markerSettingsPath_, markerJson); } -std::shared_ptr -POIManager::Impl::GetPOIByName(const std::string& name) +std::shared_ptr +MarkerManager::Impl::GetMarkerByName(const std::string& name) { - for (auto& poiRecord : poiRecords_) + for (auto& markerRecord : markerRecords_) { - if (poiRecord->name_ == name) + if (markerRecord->name_ == name) { - return poiRecord; + return markerRecord; } } return nullptr; } -POIManager::POIManager() : p(std::make_unique(this)) +MarkerManager::MarkerManager() : p(std::make_unique(this)) { // TODO THREADING? try { - p->InitializePOISettings(); + p->InitializeMarkerSettings(); - // Read POI settings on startup + // Read Marker settings on startup //main::Application::WaitForInitialization(); - p->ReadPOISettings(); + p->ReadMarkerSettings(); } catch (const std::exception& ex) { @@ -174,66 +174,66 @@ POIManager::POIManager() : p(std::make_unique(this)) } } -POIManager::~POIManager() +MarkerManager::~MarkerManager() { - p->WritePOISettings(); + p->WriteMarkerSettings(); } -size_t POIManager::poi_count() +size_t MarkerManager::marker_count() { - return p->poiRecords_.size(); + return p->markerRecords_.size(); } // TODO deal with out of range/not found -types::PointOfInterest POIManager::get_poi(size_t index) +types::MarkerInfo MarkerManager::get_marker(size_t index) { - std::shared_ptr poiRecord = - p->poiRecords_[index]; - return types::PointOfInterest( - poiRecord->name_, poiRecord->latitude_, poiRecord->longitude_); + std::shared_ptr markerRecord = + p->markerRecords_[index]; + return types::MarkerInfo( + markerRecord->name_, markerRecord->latitude_, markerRecord->longitude_); } -types::PointOfInterest POIManager::get_poi(const std::string& name) +types::MarkerInfo MarkerManager::get_marker(const std::string& name) { - std::shared_ptr poiRecord = - p->GetPOIByName(name); - return types::PointOfInterest( - poiRecord->name_, poiRecord->latitude_, poiRecord->longitude_); + std::shared_ptr markerRecord = + p->GetMarkerByName(name); + return types::MarkerInfo( + markerRecord->name_, markerRecord->latitude_, markerRecord->longitude_); } -void POIManager::set_poi(size_t index, const types::PointOfInterest& poi) +void MarkerManager::set_marker(size_t index, const types::MarkerInfo& marker) { - std::shared_ptr poiRecord = - p->poiRecords_[index]; - poiRecord->name_ = poi.name_; - poiRecord->latitude_ = poi.latitude_; - poiRecord->longitude_ = poi.longitude_; + std::shared_ptr markerRecord = + p->markerRecords_[index]; + markerRecord->name_ = marker.name_; + markerRecord->latitude_ = marker.latitude_; + markerRecord->longitude_ = marker.longitude_; } -void POIManager::set_poi(const std::string& name, - const types::PointOfInterest& poi) +void MarkerManager::set_marker(const std::string& name, + const types::MarkerInfo& marker) { - std::shared_ptr poiRecord = - p->GetPOIByName(name); - poiRecord->name_ = poi.name_; - poiRecord->latitude_ = poi.latitude_; - poiRecord->longitude_ = poi.longitude_; + std::shared_ptr markerRecord = + p->GetMarkerByName(name); + markerRecord->name_ = marker.name_; + markerRecord->latitude_ = marker.latitude_; + markerRecord->longitude_ = marker.longitude_; } -void POIManager::add_poi(const types::PointOfInterest& poi) +void MarkerManager::add_marker(const types::MarkerInfo& marker) { - p->poiRecords_.emplace_back(std::make_shared( - poi.name_, poi.latitude_, poi.longitude_)); + p->markerRecords_.emplace_back(std::make_shared( + marker.name_, marker.latitude_, marker.longitude_)); } -void POIManager::move_poi(size_t from, size_t to) +void MarkerManager::move_marker(size_t from, size_t to) { - if (from >= p->poiRecords_.size() || to >= p->poiRecords_.size()) + if (from >= p->markerRecords_.size() || to >= p->markerRecords_.size()) { return; } - std::shared_ptr poiRecord = - p->poiRecords_[from]; + std::shared_ptr markerRecord = + p->markerRecords_[from]; if (from == to) { @@ -242,33 +242,33 @@ void POIManager::move_poi(size_t from, size_t to) { for (size_t i = from; i < to; i++) { - p->poiRecords_[i] = p->poiRecords_[i + 1]; + p->markerRecords_[i] = p->markerRecords_[i + 1]; } - p->poiRecords_[to] = poiRecord; + p->markerRecords_[to] = markerRecord; } else { for (size_t i = from; i > to; i--) { - p->poiRecords_[i] = p->poiRecords_[i - 1]; + p->markerRecords_[i] = p->markerRecords_[i - 1]; } - p->poiRecords_[to] = poiRecord; + p->markerRecords_[to] = markerRecord; } } -std::shared_ptr POIManager::Instance() +std::shared_ptr MarkerManager::Instance() { - static std::weak_ptr poiManagerReference_ {}; + static std::weak_ptr markerManagerReference_ {}; - std::shared_ptr poiManager = poiManagerReference_.lock(); + std::shared_ptr markerManager = markerManagerReference_.lock(); - if (poiManager == nullptr) + if (markerManager == nullptr) { - poiManager = std::make_shared(); - poiManagerReference_ = poiManager; + markerManager = std::make_shared(); + markerManagerReference_ = markerManager; } - return poiManager; + return markerManager; } } // namespace manager diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp index 63144cc8..55631d6e 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include @@ -13,23 +13,23 @@ namespace qt namespace manager { -class POIManager : public QObject +class MarkerManager : public QObject { Q_OBJECT public: - explicit POIManager(); - ~POIManager(); + explicit MarkerManager(); + ~MarkerManager(); - size_t poi_count(); - types::PointOfInterest get_poi(size_t index); - types::PointOfInterest get_poi(const std::string& name); - void set_poi(size_t index, const types::PointOfInterest& poi); - void set_poi(const std::string& name, const types::PointOfInterest& poi); - void add_poi(const types::PointOfInterest& poi); - void move_poi(size_t from, size_t to); + size_t marker_count(); + types::MarkerInfo get_marker(size_t index); + types::MarkerInfo get_marker(const std::string& name); + void set_marker(size_t index, const types::MarkerInfo& marker); + void set_marker(const std::string& name, const types::MarkerInfo& marker); + void add_marker(const types::MarkerInfo& marker); + void move_marker(size_t from, size_t to); - static std::shared_ptr Instance(); + static std::shared_ptr Instance(); private: class Impl; diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index 4837f387..098a6378 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include #include @@ -82,7 +82,7 @@ public: radarProductLayer_ {nullptr}, overlayLayer_ {nullptr}, placefileLayer_ {nullptr}, - poiLayer_ {nullptr}, + markerLayer_ {nullptr}, colorTableLayer_ {nullptr}, autoRefreshEnabled_ {true}, autoUpdateEnabled_ {true}, @@ -225,7 +225,7 @@ public: std::shared_ptr overlayLayer_; std::shared_ptr overlayProductLayer_ {nullptr}; std::shared_ptr placefileLayer_; - std::shared_ptr poiLayer_; + std::shared_ptr markerLayer_; std::shared_ptr colorTableLayer_; std::shared_ptr radarSiteLayer_ {nullptr}; @@ -1236,9 +1236,9 @@ void MapWidgetImpl::AddLayer(types::LayerType type, break; // Create the radar site layer - case types::InformationLayer::POILayer: - poiLayer_ = std::make_shared(context_); - AddLayer(layerName, poiLayer_, before); + case types::InformationLayer::Markers: + markerLayer_ = std::make_shared(context_); + AddLayer(layerName, markerLayer_, before); break; default: diff --git a/scwx-qt/source/scwx/qt/map/marker_layer.cpp b/scwx-qt/source/scwx/qt/map/marker_layer.cpp index 4bfb4338..f899f55d 100644 --- a/scwx-qt/source/scwx/qt/map/marker_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/marker_layer.cpp @@ -1,7 +1,7 @@ -#include -#include +#include +#include #include -#include +#include #include #include @@ -12,11 +12,11 @@ namespace qt namespace map { -static const std::string logPrefix_ = "scwx::qt::map::poi_layer"; +static const std::string logPrefix_ = "scwx::qt::map::marker_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); -class POILayer::Impl +class MarkerLayer::Impl { public: explicit Impl(std::shared_ptr context) : @@ -25,65 +25,65 @@ public: } ~Impl() {} - void ReloadPOIs(); + void ReloadMarkers(); - const std::string& poiIconName_ { + const std::string& markerIconName_ { types::GetTextureName(types::ImageTexture::Cursor17)}; std::shared_ptr geoIcons_; }; -void POILayer::Impl::ReloadPOIs() +void MarkerLayer::Impl::ReloadMarkers() { - auto poiManager = manager::POIManager::Instance(); + auto markerManager = manager::MarkerManager::Instance(); geoIcons_->StartIcons(); - for (size_t i = 0; i < poiManager->poi_count(); i++) + for (size_t i = 0; i < markerManager->marker_count(); i++) { - types::PointOfInterest poi = poiManager->get_poi(i); + types::MarkerInfo marker = markerManager->get_marker(i); std::shared_ptr icon = geoIcons_->AddIcon(); - geoIcons_->SetIconTexture(icon, poiIconName_, 0); - geoIcons_->SetIconLocation(icon, poi.latitude_, poi.longitude_); + geoIcons_->SetIconTexture(icon, markerIconName_, 0); + geoIcons_->SetIconLocation(icon, marker.latitude_, marker.longitude_); } geoIcons_->FinishIcons(); } -POILayer::POILayer(const std::shared_ptr& context) : +MarkerLayer::MarkerLayer(const std::shared_ptr& context) : DrawLayer(context), - p(std::make_unique(context)) + p(std::make_unique(context)) { AddDrawItem(p->geoIcons_); } -POILayer::~POILayer() = default; +MarkerLayer::~MarkerLayer() = default; -void POILayer::Initialize() +void MarkerLayer::Initialize() { logger_->debug("Initialize()"); DrawLayer::Initialize(); p->geoIcons_->StartIconSheets(); - p->geoIcons_->AddIconSheet(p->poiIconName_); + p->geoIcons_->AddIconSheet(p->markerIconName_); p->geoIcons_->FinishIconSheets(); } -void POILayer::Render( +void MarkerLayer::Render( const QMapLibre::CustomLayerRenderParameters& params) { - //auto poiManager = manager::POIManager::Instance(); + //auto markerManager = manager::MarkerManager::Instance(); gl::OpenGLFunctions& gl = context()->gl(); // TODO. do not redo this every time - p->ReloadPOIs(); + p->ReloadMarkers(); DrawLayer::Render(params); SCWX_GL_CHECK_ERROR(); } -void POILayer::Deinitialize() +void MarkerLayer::Deinitialize() { logger_->debug("Deinitialize()"); diff --git a/scwx-qt/source/scwx/qt/map/marker_layer.hpp b/scwx-qt/source/scwx/qt/map/marker_layer.hpp index 5bc12660..9cd0674c 100644 --- a/scwx-qt/source/scwx/qt/map/marker_layer.hpp +++ b/scwx-qt/source/scwx/qt/map/marker_layer.hpp @@ -11,13 +11,13 @@ namespace qt namespace map { -class POILayer : public DrawLayer +class MarkerLayer : public DrawLayer { Q_OBJECT public: - explicit POILayer(const std::shared_ptr& context); - ~POILayer(); + explicit MarkerLayer(const std::shared_ptr& context); + ~MarkerLayer(); void Initialize() override final; void Render(const QMapLibre::CustomLayerRenderParameters&) override final; diff --git a/scwx-qt/source/scwx/qt/model/layer_model.cpp b/scwx-qt/source/scwx/qt/model/layer_model.cpp index fbc565b5..23d05cd6 100644 --- a/scwx-qt/source/scwx/qt/model/layer_model.cpp +++ b/scwx-qt/source/scwx/qt/model/layer_model.cpp @@ -43,7 +43,7 @@ static const std::vector kDefaultLayers_ { types::InformationLayer::RadarSite, false, {false, false, false, false}}, - {types::LayerType::Information, types::InformationLayer::POILayer, true}, + {types::LayerType::Information, types::InformationLayer::Markers, true}, {types::LayerType::Data, types::DataLayer::RadarRange, true}, {types::LayerType::Alert, awips::Phenomenon::Tornado, true}, {types::LayerType::Alert, awips::Phenomenon::SnowSquall, true}, diff --git a/scwx-qt/source/scwx/qt/types/layer_types.cpp b/scwx-qt/source/scwx/qt/types/layer_types.cpp index 3ab775e3..bd607cc7 100644 --- a/scwx-qt/source/scwx/qt/types/layer_types.cpp +++ b/scwx-qt/source/scwx/qt/types/layer_types.cpp @@ -31,7 +31,7 @@ static const std::unordered_map informationLayerName_ {{InformationLayer::MapOverlay, "Map Overlay"}, {InformationLayer::RadarSite, "Radar Sites"}, {InformationLayer::ColorTable, "Color Table"}, - {InformationLayer::POILayer, "Point of Interest"}, + {InformationLayer::Markers, "Location Markers"}, {InformationLayer::Unknown, "?"}}; static const std::unordered_map mapLayerName_ { diff --git a/scwx-qt/source/scwx/qt/types/layer_types.hpp b/scwx-qt/source/scwx/qt/types/layer_types.hpp index 04a4aef9..bfc10839 100644 --- a/scwx-qt/source/scwx/qt/types/layer_types.hpp +++ b/scwx-qt/source/scwx/qt/types/layer_types.hpp @@ -44,7 +44,7 @@ enum class InformationLayer MapOverlay, RadarSite, ColorTable, - POILayer, + Markers, Unknown }; diff --git a/scwx-qt/source/scwx/qt/types/marker_types.hpp b/scwx-qt/source/scwx/qt/types/marker_types.hpp index 922ea364..1fd02111 100644 --- a/scwx-qt/source/scwx/qt/types/marker_types.hpp +++ b/scwx-qt/source/scwx/qt/types/marker_types.hpp @@ -9,20 +9,16 @@ namespace qt namespace types { -struct PointOfInterest +struct MarkerInfo { - PointOfInterest(std::string name, - double latitude, - double longitude) : - name_ {name}, - latitude_ {latitude}, - longitude_ {longitude} + MarkerInfo(std::string name, double latitude, double longitude) : + name_ {name}, latitude_ {latitude}, longitude_ {longitude} { } std::string name_; - double latitude_; - double longitude_; + double latitude_; + double longitude_; }; } // namespace types From 74f3a15eb2fe127fd9b0c15d92af4b4c7390158d Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sat, 5 Oct 2024 09:24:14 -0400 Subject: [PATCH 09/30] Reformat marker formats after rename --- .../source/scwx/qt/manager/marker_manager.cpp | 29 +++++++++---------- .../source/scwx/qt/manager/marker_manager.hpp | 4 +-- scwx-qt/source/scwx/qt/map/marker_layer.cpp | 12 +++----- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp index 15e8f044..e45f4458 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp @@ -33,16 +33,15 @@ public: explicit Impl(MarkerManager* self) : self_ {self} {} ~Impl() {} - std::string markerSettingsPath_ {}; + std::string markerSettingsPath_ {}; std::vector> markerRecords_ {}; MarkerManager* self_; - void InitializeMarkerSettings(); - void ReadMarkerSettings(); - void WriteMarkerSettings(); + void InitializeMarkerSettings(); + void ReadMarkerSettings(); + void WriteMarkerSettings(); std::shared_ptr GetMarkerByName(const std::string& name); - }; class MarkerManager::Impl::MarkerRecord @@ -58,7 +57,7 @@ public: double longitude_; friend void tag_invoke(boost::json::value_from_tag, - boost::json::value& jv, + boost::json::value& jv, const std::shared_ptr& record) { jv = {{kNameName_, record->name_}, @@ -67,7 +66,7 @@ public: } friend MarkerRecord tag_invoke(boost::json::value_to_tag, - const boost::json::value& jv) + const boost::json::value& jv) { return MarkerRecord( boost::json::value_to(jv.at(kNameName_)), @@ -76,7 +75,6 @@ public: } }; - void MarkerManager::Impl::InitializeMarkerSettings() { std::string appDataPath { @@ -165,7 +163,7 @@ MarkerManager::MarkerManager() : p(std::make_unique(this)) p->InitializeMarkerSettings(); // Read Marker settings on startup - //main::Application::WaitForInitialization(); + // main::Application::WaitForInitialization(); p->ReadMarkerSettings(); } catch (const std::exception& ex) @@ -210,8 +208,8 @@ void MarkerManager::set_marker(size_t index, const types::MarkerInfo& marker) markerRecord->longitude_ = marker.longitude_; } -void MarkerManager::set_marker(const std::string& name, - const types::MarkerInfo& marker) +void MarkerManager::set_marker(const std::string& name, + const types::MarkerInfo& marker) { std::shared_ptr markerRecord = p->GetMarkerByName(name); @@ -235,9 +233,7 @@ void MarkerManager::move_marker(size_t from, size_t to) std::shared_ptr markerRecord = p->markerRecords_[from]; - if (from == to) - { - } + if (from == to) {} else if (from < to) { for (size_t i = from; i < to; i++) @@ -260,11 +256,12 @@ std::shared_ptr MarkerManager::Instance() { static std::weak_ptr markerManagerReference_ {}; - std::shared_ptr markerManager = markerManagerReference_.lock(); + std::shared_ptr markerManager = + markerManagerReference_.lock(); if (markerManager == nullptr) { - markerManager = std::make_shared(); + markerManager = std::make_shared(); markerManagerReference_ = markerManager; } diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp index 55631d6e..4fa5639c 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp @@ -21,10 +21,10 @@ public: explicit MarkerManager(); ~MarkerManager(); - size_t marker_count(); + size_t marker_count(); types::MarkerInfo get_marker(size_t index); types::MarkerInfo get_marker(const std::string& name); - void set_marker(size_t index, const types::MarkerInfo& marker); + void set_marker(size_t index, const types::MarkerInfo& marker); void set_marker(const std::string& name, const types::MarkerInfo& marker); void add_marker(const types::MarkerInfo& marker); void move_marker(size_t from, size_t to); diff --git a/scwx-qt/source/scwx/qt/map/marker_layer.cpp b/scwx-qt/source/scwx/qt/map/marker_layer.cpp index f899f55d..7b3ffb1b 100644 --- a/scwx-qt/source/scwx/qt/map/marker_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/marker_layer.cpp @@ -15,7 +15,6 @@ namespace map static const std::string logPrefix_ = "scwx::qt::map::marker_layer"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); - class MarkerLayer::Impl { public: @@ -30,7 +29,7 @@ public: const std::string& markerIconName_ { types::GetTextureName(types::ImageTexture::Cursor17)}; - std::shared_ptr geoIcons_; + std::shared_ptr geoIcons_; }; void MarkerLayer::Impl::ReloadMarkers() @@ -51,8 +50,7 @@ void MarkerLayer::Impl::ReloadMarkers() } MarkerLayer::MarkerLayer(const std::shared_ptr& context) : - DrawLayer(context), - p(std::make_unique(context)) + DrawLayer(context), p(std::make_unique(context)) { AddDrawItem(p->geoIcons_); } @@ -69,10 +67,9 @@ void MarkerLayer::Initialize() p->geoIcons_->FinishIconSheets(); } -void MarkerLayer::Render( - const QMapLibre::CustomLayerRenderParameters& params) +void MarkerLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) { - //auto markerManager = manager::MarkerManager::Instance(); + // auto markerManager = manager::MarkerManager::Instance(); gl::OpenGLFunctions& gl = context()->gl(); // TODO. do not redo this every time @@ -93,4 +90,3 @@ void MarkerLayer::Deinitialize() } // namespace map } // namespace qt } // namespace scwx - From 84233868d665a8fed4d6ec63f4d90b11a84961d4 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sat, 5 Oct 2024 09:40:43 -0400 Subject: [PATCH 10/30] Updated how MarkerRecord works to make adding entryies easier --- .../source/scwx/qt/manager/marker_manager.cpp | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp index e45f4458..f99b2ded 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp @@ -47,22 +47,29 @@ public: class MarkerManager::Impl::MarkerRecord { public: - MarkerRecord(std::string name, double latitude, double longitude) : - name_ {name}, latitude_ {latitude}, longitude_ {longitude} + MarkerRecord(const std::string& name, double latitude, double longitude) : + markerInfo_ {types::MarkerInfo(name, latitude, longitude)} + { + } + MarkerRecord(const types::MarkerInfo& info) : + markerInfo_ {info} { } - std::string name_; - double latitude_; - double longitude_; + types::MarkerInfo toMarkerInfo() + { + return markerInfo_; + } + + types::MarkerInfo markerInfo_; friend void tag_invoke(boost::json::value_from_tag, boost::json::value& jv, const std::shared_ptr& record) { - jv = {{kNameName_, record->name_}, - {kLatitudeName_, record->latitude_}, - {kLongitudeName_, record->longitude_}}; + jv = {{kNameName_, record->markerInfo_.name_}, + {kLatitudeName_, record->markerInfo_.latitude_}, + {kLongitudeName_, record->markerInfo_.longitude_}}; } friend MarkerRecord tag_invoke(boost::json::value_to_tag, @@ -117,10 +124,10 @@ void MarkerManager::Impl::ReadMarkerSettings() MarkerRecord record = boost::json::value_to(markerEntry); - if (!record.name_.empty()) + if (!record.markerInfo_.name_.empty()) { - markerRecords_.emplace_back(std::make_shared( - record.name_, record.latitude_, record.longitude_)); + markerRecords_.emplace_back( + std::make_shared(record.markerInfo_)); } } catch (const std::exception& ex) @@ -146,7 +153,7 @@ MarkerManager::Impl::GetMarkerByName(const std::string& name) { for (auto& markerRecord : markerRecords_) { - if (markerRecord->name_ == name) + if (markerRecord->markerInfo_.name_ == name) { return markerRecord; } @@ -187,25 +194,21 @@ types::MarkerInfo MarkerManager::get_marker(size_t index) { std::shared_ptr markerRecord = p->markerRecords_[index]; - return types::MarkerInfo( - markerRecord->name_, markerRecord->latitude_, markerRecord->longitude_); + return markerRecord->toMarkerInfo(); } types::MarkerInfo MarkerManager::get_marker(const std::string& name) { std::shared_ptr markerRecord = p->GetMarkerByName(name); - return types::MarkerInfo( - markerRecord->name_, markerRecord->latitude_, markerRecord->longitude_); + return markerRecord->toMarkerInfo(); } void MarkerManager::set_marker(size_t index, const types::MarkerInfo& marker) { std::shared_ptr markerRecord = p->markerRecords_[index]; - markerRecord->name_ = marker.name_; - markerRecord->latitude_ = marker.latitude_; - markerRecord->longitude_ = marker.longitude_; + markerRecord->markerInfo_ = marker; } void MarkerManager::set_marker(const std::string& name, @@ -213,15 +216,12 @@ void MarkerManager::set_marker(const std::string& name, { std::shared_ptr markerRecord = p->GetMarkerByName(name); - markerRecord->name_ = marker.name_; - markerRecord->latitude_ = marker.latitude_; - markerRecord->longitude_ = marker.longitude_; + markerRecord->markerInfo_ = marker; } void MarkerManager::add_marker(const types::MarkerInfo& marker) { - p->markerRecords_.emplace_back(std::make_shared( - marker.name_, marker.latitude_, marker.longitude_)); + p->markerRecords_.emplace_back(std::make_shared(marker)); } void MarkerManager::move_marker(size_t from, size_t to) From 19415cd0a16dad50ce30f713b904bca504a0f63b Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sat, 5 Oct 2024 13:09:55 -0400 Subject: [PATCH 11/30] Added a basic location marker manager. --- scwx-qt/scwx-qt.cmake | 8 + scwx-qt/source/scwx/qt/main/main_window.cpp | 11 + scwx-qt/source/scwx/qt/main/main_window.hpp | 1 + scwx-qt/source/scwx/qt/main/main_window.ui | 16 +- .../source/scwx/qt/manager/marker_manager.cpp | 53 ++-- .../source/scwx/qt/manager/marker_manager.hpp | 16 +- scwx-qt/source/scwx/qt/map/marker_layer.cpp | 32 ++- scwx-qt/source/scwx/qt/model/marker_model.cpp | 258 ++++++++++++++++++ scwx-qt/source/scwx/qt/model/marker_model.hpp | 51 ++++ scwx-qt/source/scwx/qt/types/marker_types.hpp | 8 +- scwx-qt/source/scwx/qt/ui/marker_dialog.cpp | 45 +++ scwx-qt/source/scwx/qt/ui/marker_dialog.hpp | 35 +++ scwx-qt/source/scwx/qt/ui/marker_dialog.ui | 88 ++++++ .../scwx/qt/ui/marker_settings_widget.cpp | 105 +++++++ .../scwx/qt/ui/marker_settings_widget.hpp | 35 +++ .../scwx/qt/ui/marker_settings_widget.ui | 88 ++++++ 16 files changed, 806 insertions(+), 44 deletions(-) create mode 100644 scwx-qt/source/scwx/qt/model/marker_model.cpp create mode 100644 scwx-qt/source/scwx/qt/model/marker_model.hpp create mode 100644 scwx-qt/source/scwx/qt/ui/marker_dialog.cpp create mode 100644 scwx-qt/source/scwx/qt/ui/marker_dialog.hpp create mode 100644 scwx-qt/source/scwx/qt/ui/marker_dialog.ui create mode 100644 scwx-qt/source/scwx/qt/ui/marker_settings_widget.cpp create mode 100644 scwx-qt/source/scwx/qt/ui/marker_settings_widget.hpp create mode 100644 scwx-qt/source/scwx/qt/ui/marker_settings_widget.ui diff --git a/scwx-qt/scwx-qt.cmake b/scwx-qt/scwx-qt.cmake index 6edb022d..71700cec 100644 --- a/scwx-qt/scwx-qt.cmake +++ b/scwx-qt/scwx-qt.cmake @@ -158,6 +158,7 @@ set(HDR_MODEL source/scwx/qt/model/alert_model.hpp source/scwx/qt/model/imgui_context_model.hpp source/scwx/qt/model/layer_model.hpp source/scwx/qt/model/placefile_model.hpp + source/scwx/qt/model/marker_model.hpp source/scwx/qt/model/radar_site_model.hpp source/scwx/qt/model/tree_item.hpp source/scwx/qt/model/tree_model.hpp) @@ -166,6 +167,7 @@ set(SRC_MODEL source/scwx/qt/model/alert_model.cpp source/scwx/qt/model/imgui_context_model.cpp source/scwx/qt/model/layer_model.cpp source/scwx/qt/model/placefile_model.cpp + source/scwx/qt/model/marker_model.cpp source/scwx/qt/model/radar_site_model.cpp source/scwx/qt/model/tree_item.cpp source/scwx/qt/model/tree_model.cpp) @@ -265,6 +267,8 @@ set(HDR_UI source/scwx/qt/ui/about_dialog.hpp source/scwx/qt/ui/open_url_dialog.hpp source/scwx/qt/ui/placefile_dialog.hpp source/scwx/qt/ui/placefile_settings_widget.hpp + source/scwx/qt/ui/marker_dialog.hpp + source/scwx/qt/ui/marker_settings_widget.hpp source/scwx/qt/ui/progress_dialog.hpp source/scwx/qt/ui/radar_site_dialog.hpp source/scwx/qt/ui/serial_port_dialog.hpp @@ -293,6 +297,8 @@ set(SRC_UI source/scwx/qt/ui/about_dialog.cpp source/scwx/qt/ui/open_url_dialog.cpp source/scwx/qt/ui/placefile_dialog.cpp source/scwx/qt/ui/placefile_settings_widget.cpp + source/scwx/qt/ui/marker_dialog.cpp + source/scwx/qt/ui/marker_settings_widget.cpp source/scwx/qt/ui/progress_dialog.cpp source/scwx/qt/ui/radar_site_dialog.cpp source/scwx/qt/ui/settings_dialog.cpp @@ -312,6 +318,8 @@ set(UI_UI source/scwx/qt/ui/about_dialog.ui source/scwx/qt/ui/open_url_dialog.ui source/scwx/qt/ui/placefile_dialog.ui source/scwx/qt/ui/placefile_settings_widget.ui + source/scwx/qt/ui/marker_dialog.ui + source/scwx/qt/ui/marker_settings_widget.ui source/scwx/qt/ui/progress_dialog.ui source/scwx/qt/ui/radar_site_dialog.ui source/scwx/qt/ui/settings_dialog.ui diff --git a/scwx-qt/source/scwx/qt/main/main_window.cpp b/scwx-qt/source/scwx/qt/main/main_window.cpp index 836d6784..ac5f73e1 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.cpp +++ b/scwx-qt/source/scwx/qt/main/main_window.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -87,6 +88,7 @@ public: imGuiDebugDialog_ {nullptr}, layerDialog_ {nullptr}, placefileDialog_ {nullptr}, + markerDialog_ {nullptr}, radarSiteDialog_ {nullptr}, settingsDialog_ {nullptr}, updateDialog_ {nullptr}, @@ -205,6 +207,7 @@ public: ui::ImGuiDebugDialog* imGuiDebugDialog_; ui::LayerDialog* layerDialog_; ui::PlacefileDialog* placefileDialog_; + ui::MarkerDialog* markerDialog_; ui::RadarSiteDialog* radarSiteDialog_; ui::SettingsDialog* settingsDialog_; ui::UpdateDialog* updateDialog_; @@ -306,6 +309,9 @@ MainWindow::MainWindow(QWidget* parent) : // Placefile Manager Dialog p->placefileDialog_ = new ui::PlacefileDialog(this); + // Marker Manager Dialog + p->markerDialog_ = new ui::MarkerDialog(this); + // Layer Dialog p->layerDialog_ = new ui::LayerDialog(this); @@ -613,6 +619,11 @@ void MainWindow::on_actionPlacefileManager_triggered() p->placefileDialog_->show(); } +void MainWindow::on_actionMarkerManager_triggered() +{ + p->markerDialog_->show(); +} + void MainWindow::on_actionLayerManager_triggered() { p->layerDialog_->show(); diff --git a/scwx-qt/source/scwx/qt/main/main_window.hpp b/scwx-qt/source/scwx/qt/main/main_window.hpp index c6ea3a5f..6a4fb5b4 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.hpp +++ b/scwx-qt/source/scwx/qt/main/main_window.hpp @@ -44,6 +44,7 @@ private slots: void on_actionRadarRange_triggered(bool checked); void on_actionRadarSites_triggered(bool checked); void on_actionPlacefileManager_triggered(); + void on_actionMarkerManager_triggered(); void on_actionLayerManager_triggered(); void on_actionImGuiDebug_triggered(); void on_actionDumpLayerList_triggered(); diff --git a/scwx-qt/source/scwx/qt/main/main_window.ui b/scwx-qt/source/scwx/qt/main/main_window.ui index 9fab1adf..c5e877c9 100644 --- a/scwx-qt/source/scwx/qt/main/main_window.ui +++ b/scwx-qt/source/scwx/qt/main/main_window.ui @@ -39,7 +39,7 @@ 0 0 1024 - 33 + 22 @@ -104,6 +104,7 @@ + @@ -152,8 +153,8 @@ 0 0 - 190 - 686 + 205 + 701 @@ -487,6 +488,15 @@ &GPS Info + + + + :/res/icons/font-awesome-6/house-solid.svg:/res/icons/font-awesome-6/house-solid.svg + + + Location &Marker Manager + + diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp index f99b2ded..15dc0509 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp @@ -56,7 +56,7 @@ public: { } - types::MarkerInfo toMarkerInfo() + const types::MarkerInfo& toMarkerInfo() { return markerInfo_; } @@ -67,9 +67,9 @@ public: boost::json::value& jv, const std::shared_ptr& record) { - jv = {{kNameName_, record->markerInfo_.name_}, - {kLatitudeName_, record->markerInfo_.latitude_}, - {kLongitudeName_, record->markerInfo_.longitude_}}; + jv = {{kNameName_, record->markerInfo_.name}, + {kLatitudeName_, record->markerInfo_.latitude}, + {kLongitudeName_, record->markerInfo_.longitude}}; } friend MarkerRecord tag_invoke(boost::json::value_to_tag, @@ -124,7 +124,7 @@ void MarkerManager::Impl::ReadMarkerSettings() MarkerRecord record = boost::json::value_to(markerEntry); - if (!record.markerInfo_.name_.empty()) + if (!record.markerInfo_.name.empty()) { markerRecords_.emplace_back( std::make_shared(record.markerInfo_)); @@ -138,6 +138,8 @@ void MarkerManager::Impl::ReadMarkerSettings() logger_->debug("{} location marker entries", markerRecords_.size()); } + + Q_EMIT self_->MarkersUpdated(); } void MarkerManager::Impl::WriteMarkerSettings() @@ -153,7 +155,7 @@ MarkerManager::Impl::GetMarkerByName(const std::string& name) { for (auto& markerRecord : markerRecords_) { - if (markerRecord->markerInfo_.name_ == name) + if (markerRecord->markerInfo_.name == name) { return markerRecord; } @@ -190,38 +192,44 @@ size_t MarkerManager::marker_count() } // TODO deal with out of range/not found -types::MarkerInfo MarkerManager::get_marker(size_t index) +const types::MarkerInfo& MarkerManager::get_marker(size_t index) { std::shared_ptr markerRecord = p->markerRecords_[index]; return markerRecord->toMarkerInfo(); } -types::MarkerInfo MarkerManager::get_marker(const std::string& name) -{ - std::shared_ptr markerRecord = - p->GetMarkerByName(name); - return markerRecord->toMarkerInfo(); -} - void MarkerManager::set_marker(size_t index, const types::MarkerInfo& marker) { std::shared_ptr markerRecord = p->markerRecords_[index]; markerRecord->markerInfo_ = marker; -} - -void MarkerManager::set_marker(const std::string& name, - const types::MarkerInfo& marker) -{ - std::shared_ptr markerRecord = - p->GetMarkerByName(name); - markerRecord->markerInfo_ = marker; + Q_EMIT MarkersUpdated(); } void MarkerManager::add_marker(const types::MarkerInfo& marker) { p->markerRecords_.emplace_back(std::make_shared(marker)); + Q_EMIT MarkerAdded(); + Q_EMIT MarkersUpdated(); +} + +void MarkerManager::remove_marker(size_t index) +{ + if (index >= p->markerRecords_.size()) + { + return; + } + + for (size_t i = index; i < p->markerRecords_.size() - 1; i++) + { + p->markerRecords_[i] = p->markerRecords_[i + 1]; + } + + p->markerRecords_.pop_back(); + + Q_EMIT MarkerRemoved(index); + Q_EMIT MarkersUpdated(); } void MarkerManager::move_marker(size_t from, size_t to) @@ -250,6 +258,7 @@ void MarkerManager::move_marker(size_t from, size_t to) } p->markerRecords_[to] = markerRecord; } + Q_EMIT MarkersUpdated(); } std::shared_ptr MarkerManager::Instance() diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp index 4fa5639c..e21accbf 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp @@ -2,8 +2,6 @@ #include -#include - #include namespace scwx @@ -21,16 +19,20 @@ public: explicit MarkerManager(); ~MarkerManager(); - size_t marker_count(); - types::MarkerInfo get_marker(size_t index); - types::MarkerInfo get_marker(const std::string& name); - void set_marker(size_t index, const types::MarkerInfo& marker); - void set_marker(const std::string& name, const types::MarkerInfo& marker); + size_t marker_count(); + const types::MarkerInfo& get_marker(size_t index); + void set_marker(size_t index, const types::MarkerInfo& marker); void add_marker(const types::MarkerInfo& marker); + void remove_marker(size_t index); void move_marker(size_t from, size_t to); static std::shared_ptr Instance(); +signals: + void MarkersUpdated(); + void MarkerAdded(); + void MarkerRemoved(size_t index); + private: class Impl; std::unique_ptr p; diff --git a/scwx-qt/source/scwx/qt/map/marker_layer.cpp b/scwx-qt/source/scwx/qt/map/marker_layer.cpp index 7b3ffb1b..1a09a0c6 100644 --- a/scwx-qt/source/scwx/qt/map/marker_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/marker_layer.cpp @@ -18,39 +18,56 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_); class MarkerLayer::Impl { public: - explicit Impl(std::shared_ptr context) : - geoIcons_ {std::make_shared(context)} + explicit Impl(MarkerLayer* self, std::shared_ptr context) : + self_ {self}, geoIcons_ {std::make_shared(context)} { + ConnectSignals(); } ~Impl() {} void ReloadMarkers(); + void ConnectSignals(); + MarkerLayer* self_; const std::string& markerIconName_ { types::GetTextureName(types::ImageTexture::Cursor17)}; std::shared_ptr geoIcons_; }; +void MarkerLayer::Impl::ConnectSignals() +{ + auto markerManager = manager::MarkerManager::Instance(); + + QObject::connect(markerManager.get(), + &manager::MarkerManager::MarkersUpdated, + self_, + [this]() + { + this->ReloadMarkers(); + }); +} + void MarkerLayer::Impl::ReloadMarkers() { + logger_->debug("ReloadMarkers()"); auto markerManager = manager::MarkerManager::Instance(); geoIcons_->StartIcons(); for (size_t i = 0; i < markerManager->marker_count(); i++) { - types::MarkerInfo marker = markerManager->get_marker(i); + const types::MarkerInfo& marker = markerManager->get_marker(i); std::shared_ptr icon = geoIcons_->AddIcon(); geoIcons_->SetIconTexture(icon, markerIconName_, 0); - geoIcons_->SetIconLocation(icon, marker.latitude_, marker.longitude_); + geoIcons_->SetIconLocation(icon, marker.latitude, marker.longitude); } geoIcons_->FinishIcons(); } MarkerLayer::MarkerLayer(const std::shared_ptr& context) : - DrawLayer(context), p(std::make_unique(context)) + DrawLayer(context), p(std::make_unique(this, context)) { AddDrawItem(p->geoIcons_); } @@ -65,6 +82,8 @@ void MarkerLayer::Initialize() p->geoIcons_->StartIconSheets(); p->geoIcons_->AddIconSheet(p->markerIconName_); p->geoIcons_->FinishIconSheets(); + + p->ReloadMarkers(); } void MarkerLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) @@ -72,9 +91,6 @@ void MarkerLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) // auto markerManager = manager::MarkerManager::Instance(); gl::OpenGLFunctions& gl = context()->gl(); - // TODO. do not redo this every time - p->ReloadMarkers(); - DrawLayer::Render(params); SCWX_GL_CHECK_ERROR(); diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp new file mode 100644 index 00000000..3061c764 --- /dev/null +++ b/scwx-qt/source/scwx/qt/model/marker_model.cpp @@ -0,0 +1,258 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace scwx +{ +namespace qt +{ +namespace model +{ + +static const std::string logPrefix_ = "scwx::qt::model::marker_model"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + +static constexpr int kFirstColumn = + static_cast(MarkerModel::Column::Name); +static constexpr int kLastColumn = + static_cast(MarkerModel::Column::Longitude); +static constexpr int kNumColumns = kLastColumn - kFirstColumn + 1; + +class MarkerModel::Impl +{ +public: + explicit Impl() {} + ~Impl() = default; + std::shared_ptr markerManager_ { + manager::MarkerManager::Instance()}; +}; + +MarkerModel::MarkerModel(QObject* parent) : + QAbstractTableModel(parent), p(std::make_unique()) +{ + connect(p->markerManager_.get(), + &manager::MarkerManager::MarkerAdded, + this, + &MarkerModel::HandleMarkerAdded); +} + +MarkerModel::~MarkerModel() = default; + +int MarkerModel::rowCount(const QModelIndex& parent) const +{ + return parent.isValid() ? + 0 : + static_cast(p->markerManager_->marker_count()); +} + +int MarkerModel::columnCount(const QModelIndex& parent) const +{ + return parent.isValid() ? 0 : kNumColumns; +} + +Qt::ItemFlags MarkerModel::flags(const QModelIndex& index) const +{ + Qt::ItemFlags flags = QAbstractTableModel::flags(index); + + switch (index.column()) + { + case static_cast(Column::Name): + case static_cast(Column::Latitude): + case static_cast(Column::Longitude): + flags |= Qt::ItemFlag::ItemIsEditable; + break; + default: + break; + } + + return flags; +} + +QVariant MarkerModel::data(const QModelIndex& index, int role) const +{ + + static const char COORDINATE_FORMAT = 'g'; + static const int COORDINATE_PRECISION = 6; + + if (!index.isValid() || index.row() < 0 || + static_cast(index.row()) >= + p->markerManager_->marker_count()) + { + return QVariant(); + } + + const types::MarkerInfo markerInfo = + p->markerManager_->get_marker(index.row()); + + switch(index.column()) + { + case static_cast(Column::Name): + if (role == Qt::ItemDataRole::DisplayRole || + role == Qt::ItemDataRole::ToolTipRole || + role == Qt::ItemDataRole::EditRole) + { + return QString::fromStdString(markerInfo.name); + } + break; + + case static_cast(Column::Latitude): + if (role == Qt::ItemDataRole::DisplayRole || + role == Qt::ItemDataRole::ToolTipRole || + role == Qt::ItemDataRole::EditRole) + { + return QString::number( + markerInfo.latitude, COORDINATE_FORMAT, COORDINATE_PRECISION); + } + break; + + case static_cast(Column::Longitude): + if (role == Qt::ItemDataRole::DisplayRole || + role == Qt::ItemDataRole::ToolTipRole || + role == Qt::ItemDataRole::EditRole) + { + return QString::number( + markerInfo.longitude, COORDINATE_FORMAT, COORDINATE_PRECISION); + } + break; + + default: + break; + } + + return QVariant(); +} + +QVariant MarkerModel::headerData(int section, + Qt::Orientation orientation, + int role) const +{ + if (role == Qt::ItemDataRole::DisplayRole) + { + if (orientation == Qt::Horizontal) + { + switch (section) + { + case static_cast(Column::Name): + return tr("Name"); + + case static_cast(Column::Latitude): + return tr("Latitude"); + + case static_cast(Column::Longitude): + return tr("Longitude"); + + default: + break; + } + } + } + + return QVariant(); +} + +bool MarkerModel::setData(const QModelIndex& index, + const QVariant& value, + int role) +{ + if (!index.isValid() || index.row() < 0 || + static_cast(index.row()) >= + p->markerManager_->marker_count()) + { + return false; + } + + types::MarkerInfo markerInfo = p->markerManager_->get_marker(index.row()); + bool result = false; + + switch(index.column()) + { + case static_cast(Column::Name): + if (role == Qt::ItemDataRole::EditRole) + { + QString str = value.toString(); + markerInfo.name = str.toStdString(); + p->markerManager_->set_marker(index.row(), markerInfo); + result = true; + } + break; + + case static_cast(Column::Latitude): + if (role == Qt::ItemDataRole::EditRole) + { + QString str = value.toString(); + bool ok; + double latitude = str.toDouble(&ok); + if (str.isEmpty()) + { + markerInfo.latitude = 0; + p->markerManager_->set_marker(index.row(), markerInfo); + result = true; + } + else if (ok) + { + markerInfo.latitude = latitude; + p->markerManager_->set_marker(index.row(), markerInfo); + result = true; + } + } + break; + + case static_cast(Column::Longitude): + if (role == Qt::ItemDataRole::EditRole) + { + QString str = value.toString(); + bool ok; + double longitude = str.toDouble(&ok); + if (str.isEmpty()) + { + markerInfo.longitude = 0; + p->markerManager_->set_marker(index.row(), markerInfo); + result = true; + } + else if (ok) + { + markerInfo.longitude = longitude; + p->markerManager_->set_marker(index.row(), markerInfo); + result = true; + } + } + break; + + default: + break; + } + + if (result) + { + Q_EMIT dataChanged(index, index); + } + + return result; +} + +void MarkerModel::HandleMarkerAdded() +{ + QModelIndex topLeft = createIndex(0, kFirstColumn); + QModelIndex bottomRight = + createIndex(p->markerManager_->marker_count() - 1, kLastColumn); + + logger_->debug("marker_count: {}", p->markerManager_->marker_count()); + + const int newIndex = static_cast(p->markerManager_->marker_count() - 1); + beginInsertRows(QModelIndex(), newIndex, newIndex); + endInsertRows(); + + Q_EMIT dataChanged(topLeft, bottomRight); +} + +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/marker_model.hpp b/scwx-qt/source/scwx/qt/model/marker_model.hpp new file mode 100644 index 00000000..a3d23546 --- /dev/null +++ b/scwx-qt/source/scwx/qt/model/marker_model.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include + +namespace scwx +{ +namespace qt +{ +namespace model +{ + +class MarkerModel : public QAbstractTableModel +{ +public: + enum class Column : int + { + Name = 0, + Latitude = 1, + Longitude = 2 + }; + + explicit MarkerModel(QObject* parent = nullptr); + ~MarkerModel(); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + int columnCount(const QModelIndex& parent = QModelIndex()) const override; + + Qt::ItemFlags flags(const QModelIndex& index) const override; + + QVariant data(const QModelIndex& index, + int role = Qt::DisplayRole) const override; + QVariant headerData(int section, + Qt::Orientation orientation, + int role = Qt::DisplayRole) const override; + + bool setData(const QModelIndex& index, + const QVariant& value, + int role = Qt::EditRole) override; + + +public slots: + void HandleMarkerAdded(); + +private: + class Impl; + std::unique_ptr p; +}; + +} // namespace model +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/types/marker_types.hpp b/scwx-qt/source/scwx/qt/types/marker_types.hpp index 1fd02111..ffa94b3d 100644 --- a/scwx-qt/source/scwx/qt/types/marker_types.hpp +++ b/scwx-qt/source/scwx/qt/types/marker_types.hpp @@ -12,13 +12,13 @@ namespace types struct MarkerInfo { MarkerInfo(std::string name, double latitude, double longitude) : - name_ {name}, latitude_ {latitude}, longitude_ {longitude} + name {name}, latitude {latitude}, longitude {longitude} { } - std::string name_; - double latitude_; - double longitude_; + std::string name; + double latitude; + double longitude; }; } // namespace types diff --git a/scwx-qt/source/scwx/qt/ui/marker_dialog.cpp b/scwx-qt/source/scwx/qt/ui/marker_dialog.cpp new file mode 100644 index 00000000..3db33a06 --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/marker_dialog.cpp @@ -0,0 +1,45 @@ +#include "marker_dialog.hpp" +#include "ui_marker_dialog.h" + +#include +#include + +namespace scwx +{ +namespace qt +{ +namespace ui +{ + +static const std::string logPrefix_ = "scwx::qt::ui::marker_dialog"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + +class MarkerDialogImpl +{ +public: + explicit MarkerDialogImpl() {} + ~MarkerDialogImpl() = default; + + MarkerSettingsWidget* markerSettingsWidget_ {nullptr}; +}; + +MarkerDialog::MarkerDialog(QWidget* parent) : + QDialog(parent), + p {std::make_unique()}, + ui(new Ui::MarkerDialog) +{ + ui->setupUi(this); + + p->markerSettingsWidget_ = new MarkerSettingsWidget(this); + p->markerSettingsWidget_->layout()->setContentsMargins(0, 0, 0, 0); + ui->contentsFrame->layout()->addWidget(p->markerSettingsWidget_); +} + +MarkerDialog::~MarkerDialog() +{ + delete ui; +} + +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/marker_dialog.hpp b/scwx-qt/source/scwx/qt/ui/marker_dialog.hpp new file mode 100644 index 00000000..4a9503e9 --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/marker_dialog.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +namespace Ui +{ +class MarkerDialog; +} + +namespace scwx +{ +namespace qt +{ +namespace ui +{ + +class MarkerDialogImpl; + +class MarkerDialog : public QDialog +{ + Q_OBJECT + +public: + explicit MarkerDialog(QWidget* parent = nullptr); + ~MarkerDialog(); + +private: + friend class MarkerDialogImpl; + std::unique_ptr p; + Ui::MarkerDialog* ui; +}; + +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/marker_dialog.ui b/scwx-qt/source/scwx/qt/ui/marker_dialog.ui new file mode 100644 index 00000000..641775a5 --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/marker_dialog.ui @@ -0,0 +1,88 @@ + + + MarkerDialog + + + + 0 + 0 + 700 + 600 + + + + Marker Manager + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + + + buttonBox + accepted() + MarkerDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + MarkerDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/scwx-qt/source/scwx/qt/ui/marker_settings_widget.cpp b/scwx-qt/source/scwx/qt/ui/marker_settings_widget.cpp new file mode 100644 index 00000000..8fc1fe6a --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/marker_settings_widget.cpp @@ -0,0 +1,105 @@ +#include "marker_settings_widget.hpp" +#include "ui_marker_settings_widget.h" + +#include +#include +#include +#include +#include + +#include + +namespace scwx +{ +namespace qt +{ +namespace ui +{ + +static const std::string logPrefix_ = "scwx::qt::ui::marker_settings_widget"; +static const auto logger_ = scwx::util::Logger::Create(logPrefix_); + +class MarkerSettingsWidgetImpl +{ +public: + explicit MarkerSettingsWidgetImpl(MarkerSettingsWidget* self) : + self_ {self}, + markerModel_ {new model::MarkerModel(self_)} + { + } + + void ConnectSignals(); + + MarkerSettingsWidget* self_; + model::MarkerModel* markerModel_; + std::shared_ptr markerManager_ { + manager::MarkerManager::Instance()}; +}; + + +MarkerSettingsWidget::MarkerSettingsWidget(QWidget* parent) : + QFrame(parent), + p {std::make_unique(this)}, + ui(new Ui::MarkerSettingsWidget) +{ + ui->setupUi(this); + + ui->removeButton->setEnabled(false); + + ui->markerView->setModel(p->markerModel_); + + p->ConnectSignals(); +} + +MarkerSettingsWidget::~MarkerSettingsWidget() +{ + delete ui; +} + +void MarkerSettingsWidgetImpl::ConnectSignals() +{ + QObject::connect(self_->ui->addButton, + &QPushButton::clicked, + self_, + [this]() + { + markerManager_->add_marker(types::MarkerInfo("", 0, 0)); + }); + QObject::connect(self_->ui->removeButton, + &QPushButton::clicked, + self_, + [this]() + { + auto selectionModel = + self_->ui->markerView->selectionModel(); + QModelIndex selected = + selectionModel + ->selectedRows(static_cast( + model::MarkerModel::Column::Name)) + .first(); + + markerManager_->remove_marker(selected.row()); + }); + QObject::connect( + self_->ui->markerView->selectionModel(), + &QItemSelectionModel::selectionChanged, + self_, + [this](const QItemSelection& selected, const QItemSelection& deselected) + { + if (selected.size() == 0 && deselected.size() == 0) + { + // Items which stay selected but change their index are not + // included in selected and deselected. Thus, this signal might + // be emitted with both selected and deselected empty, if only + // the indices of selected items change. + return; + } + + bool itemSelected = selected.size() > 0; + self_->ui->removeButton->setEnabled(itemSelected); + }); +} + +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/marker_settings_widget.hpp b/scwx-qt/source/scwx/qt/ui/marker_settings_widget.hpp new file mode 100644 index 00000000..b784c418 --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/marker_settings_widget.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +namespace Ui +{ +class MarkerSettingsWidget; +} + +namespace scwx +{ +namespace qt +{ +namespace ui +{ + +class MarkerSettingsWidgetImpl; + +class MarkerSettingsWidget : public QFrame +{ + Q_OBJECT + +public: + explicit MarkerSettingsWidget(QWidget* parent = nullptr); + ~MarkerSettingsWidget(); + +private: + friend class MarkerSettingsWidgetImpl; + std::unique_ptr p; + Ui::MarkerSettingsWidget* ui; +}; + +} // namespace ui +} // namespace qt +} // namespace scwx diff --git a/scwx-qt/source/scwx/qt/ui/marker_settings_widget.ui b/scwx-qt/source/scwx/qt/ui/marker_settings_widget.ui new file mode 100644 index 00000000..12315d24 --- /dev/null +++ b/scwx-qt/source/scwx/qt/ui/marker_settings_widget.ui @@ -0,0 +1,88 @@ + + + MarkerSettingsWidget + + + + 0 + 0 + 400 + 300 + + + + Frame + + + + + + true + + + 0 + + + true + + + + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + &Add + + + + + + + false + + + R&emove + + + + + + + + + + + From 20fd03bbdb05450bd56f5706d66d9984a58a0531 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sat, 5 Oct 2024 14:23:11 -0400 Subject: [PATCH 12/30] modified code to avoid cast from size_t to int properly --- scwx-qt/source/scwx/qt/model/marker_model.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp index 3061c764..6dbd46bc 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.cpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.cpp @@ -241,12 +241,9 @@ bool MarkerModel::setData(const QModelIndex& index, void MarkerModel::HandleMarkerAdded() { QModelIndex topLeft = createIndex(0, kFirstColumn); - QModelIndex bottomRight = - createIndex(p->markerManager_->marker_count() - 1, kLastColumn); - - logger_->debug("marker_count: {}", p->markerManager_->marker_count()); - const int newIndex = static_cast(p->markerManager_->marker_count() - 1); + QModelIndex bottomRight = createIndex(newIndex, kLastColumn); + beginInsertRows(QModelIndex(), newIndex, newIndex); endInsertRows(); From 9730ae581b2ab1d6f15aca54ead8e38a8dda5d2d Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sun, 6 Oct 2024 12:12:27 -0400 Subject: [PATCH 13/30] fix missed update of comment after copy/paste --- scwx-qt/source/scwx/qt/map/map_widget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scwx-qt/source/scwx/qt/map/map_widget.cpp b/scwx-qt/source/scwx/qt/map/map_widget.cpp index 098a6378..da5bef38 100644 --- a/scwx-qt/source/scwx/qt/map/map_widget.cpp +++ b/scwx-qt/source/scwx/qt/map/map_widget.cpp @@ -1235,7 +1235,7 @@ void MapWidgetImpl::AddLayer(types::LayerType type, { widget_->RadarSiteRequested(id); }); break; - // Create the radar site layer + // Create the location marker layer case types::InformationLayer::Markers: markerLayer_ = std::make_shared(context_); AddLayer(layerName, markerLayer_, before); From ad10e019fe88ab95b7055730216185575d8b09ee Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sun, 6 Oct 2024 12:13:00 -0400 Subject: [PATCH 14/30] use referance to avoid unnecessary copy --- scwx-qt/source/scwx/qt/types/marker_types.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scwx-qt/source/scwx/qt/types/marker_types.hpp b/scwx-qt/source/scwx/qt/types/marker_types.hpp index ffa94b3d..0d9c575b 100644 --- a/scwx-qt/source/scwx/qt/types/marker_types.hpp +++ b/scwx-qt/source/scwx/qt/types/marker_types.hpp @@ -11,7 +11,7 @@ namespace types struct MarkerInfo { - MarkerInfo(std::string name, double latitude, double longitude) : + MarkerInfo(const std::string& name, double latitude, double longitude) : name {name}, latitude {latitude}, longitude {longitude} { } From 57625b9680cc7f2832a833fc24d23d738c52f7b2 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sun, 6 Oct 2024 12:15:40 -0400 Subject: [PATCH 15/30] Add async code to marker_manager --- .../source/scwx/qt/manager/marker_manager.cpp | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp index 15dc0509..116f1c3b 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp @@ -10,6 +10,8 @@ #include #include +#include +#include namespace scwx { @@ -31,13 +33,15 @@ public: class MarkerRecord; explicit Impl(MarkerManager* self) : self_ {self} {} - ~Impl() {} + ~Impl() { threadPool_.join(); } std::string markerSettingsPath_ {}; std::vector> markerRecords_ {}; MarkerManager* self_; + boost::asio::thread_pool threadPool_ {1u}; + void InitializeMarkerSettings(); void ReadMarkerSettings(); void WriteMarkerSettings(); @@ -166,19 +170,23 @@ MarkerManager::Impl::GetMarkerByName(const std::string& name) MarkerManager::MarkerManager() : p(std::make_unique(this)) { - // TODO THREADING? - try - { - p->InitializeMarkerSettings(); - // Read Marker settings on startup - // main::Application::WaitForInitialization(); - p->ReadMarkerSettings(); - } - catch (const std::exception& ex) - { - logger_->error(ex.what()); - } + boost::asio::post(p->threadPool_, + [this]() + { + try + { + p->InitializeMarkerSettings(); + + // Read Marker settings on startup + main::Application::WaitForInitialization(); + p->ReadMarkerSettings(); + } + catch (const std::exception& ex) + { + logger_->error(ex.what()); + } + }); } MarkerManager::~MarkerManager() @@ -264,6 +272,9 @@ void MarkerManager::move_marker(size_t from, size_t to) std::shared_ptr MarkerManager::Instance() { static std::weak_ptr markerManagerReference_ {}; + static std::mutex instanceMutex_ {}; + + std::unique_lock lock(instanceMutex_); std::shared_ptr markerManager = markerManagerReference_.lock(); From 491a33794f714b42a8b3fcf5690a20947bca63f4 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sun, 6 Oct 2024 12:18:22 -0400 Subject: [PATCH 16/30] Updated MarkerModel to update correctly on add/remove --- scwx-qt/source/scwx/qt/model/marker_model.cpp | 19 ++++++++++++++++++- scwx-qt/source/scwx/qt/model/marker_model.hpp | 1 + 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp index 6dbd46bc..3f137c8c 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.cpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.cpp @@ -42,6 +42,11 @@ MarkerModel::MarkerModel(QObject* parent) : &manager::MarkerManager::MarkerAdded, this, &MarkerModel::HandleMarkerAdded); + + connect(p->markerManager_.get(), + &manager::MarkerManager::MarkerRemoved, + this, + &MarkerModel::HandleMarkerRemoved); } MarkerModel::~MarkerModel() = default; @@ -240,8 +245,8 @@ bool MarkerModel::setData(const QModelIndex& index, void MarkerModel::HandleMarkerAdded() { - QModelIndex topLeft = createIndex(0, kFirstColumn); const int newIndex = static_cast(p->markerManager_->marker_count() - 1); + QModelIndex topLeft = createIndex(newIndex, kFirstColumn); QModelIndex bottomRight = createIndex(newIndex, kLastColumn); beginInsertRows(QModelIndex(), newIndex, newIndex); @@ -250,6 +255,18 @@ void MarkerModel::HandleMarkerAdded() Q_EMIT dataChanged(topLeft, bottomRight); } +void MarkerModel::HandleMarkerRemoved(size_t index) +{ + const int removedIndex = static_cast(index); + QModelIndex topLeft = createIndex(removedIndex, kFirstColumn); + QModelIndex bottomRight = createIndex(removedIndex, kLastColumn); + + beginRemoveRows(QModelIndex(), removedIndex, removedIndex); + endRemoveRows(); + + Q_EMIT dataChanged(topLeft, bottomRight); +} + } // namespace model } // namespace qt } // namespace scwx diff --git a/scwx-qt/source/scwx/qt/model/marker_model.hpp b/scwx-qt/source/scwx/qt/model/marker_model.hpp index a3d23546..9c640238 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.hpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.hpp @@ -40,6 +40,7 @@ public: public slots: void HandleMarkerAdded(); + void HandleMarkerRemoved(size_t index); private: class Impl; From 534b679d63caa1018b8a9459655a97d07cb3f846 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sun, 6 Oct 2024 12:19:54 -0400 Subject: [PATCH 17/30] Use std::vector::erase instead of self written code in remove_marker --- scwx-qt/source/scwx/qt/manager/marker_manager.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp index 116f1c3b..e4cce9e6 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp @@ -229,12 +229,7 @@ void MarkerManager::remove_marker(size_t index) return; } - for (size_t i = index; i < p->markerRecords_.size() - 1; i++) - { - p->markerRecords_[i] = p->markerRecords_[i + 1]; - } - - p->markerRecords_.pop_back(); + p->markerRecords_.erase(std::next(p->markerRecords_.begin(), index)); Q_EMIT MarkerRemoved(index); Q_EMIT MarkersUpdated(); From 250a535fc3b5dc139019e79873b93560f220487a Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sun, 6 Oct 2024 12:21:21 -0400 Subject: [PATCH 18/30] Add proper bounds checks and update usage of references in marker_manager.cpp --- .../source/scwx/qt/manager/marker_manager.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp index e4cce9e6..d74fe09f 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp @@ -199,17 +199,24 @@ size_t MarkerManager::marker_count() return p->markerRecords_.size(); } -// TODO deal with out of range/not found -const types::MarkerInfo& MarkerManager::get_marker(size_t index) +std::optional MarkerManager::get_marker(size_t index) { - std::shared_ptr markerRecord = + if (index >= p->markerRecords_.size()) + { + return {}; + } + std::shared_ptr& markerRecord = p->markerRecords_[index]; return markerRecord->toMarkerInfo(); } void MarkerManager::set_marker(size_t index, const types::MarkerInfo& marker) { - std::shared_ptr markerRecord = + if (index >= p->markerRecords_.size()) + { + return; + } + std::shared_ptr& markerRecord = p->markerRecords_[index]; markerRecord->markerInfo_ = marker; Q_EMIT MarkersUpdated(); @@ -241,7 +248,7 @@ void MarkerManager::move_marker(size_t from, size_t to) { return; } - std::shared_ptr markerRecord = + std::shared_ptr& markerRecord = p->markerRecords_[from]; if (from == to) {} From 0ec81e5832121215ff45b2703d23c006270fab0b Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sun, 6 Oct 2024 12:22:04 -0400 Subject: [PATCH 19/30] Add modified methods to header file from last commit --- scwx-qt/source/scwx/qt/manager/marker_manager.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp index e21accbf..4fb81457 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace scwx { @@ -20,7 +21,7 @@ public: ~MarkerManager(); size_t marker_count(); - const types::MarkerInfo& get_marker(size_t index); + std::optional get_marker(size_t index); void set_marker(size_t index, const types::MarkerInfo& marker); void add_marker(const types::MarkerInfo& marker); void remove_marker(size_t index); From 0cfad829332e26ab2044d65e4f2ec944723cb069 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sun, 6 Oct 2024 12:23:45 -0400 Subject: [PATCH 20/30] Modify usage of get_marker for updated interface, and update checks for lat/lon input --- scwx-qt/source/scwx/qt/map/marker_layer.cpp | 8 ++- scwx-qt/source/scwx/qt/model/marker_model.cpp | 56 ++++++++----------- 2 files changed, 30 insertions(+), 34 deletions(-) diff --git a/scwx-qt/source/scwx/qt/map/marker_layer.cpp b/scwx-qt/source/scwx/qt/map/marker_layer.cpp index 1a09a0c6..545b6c32 100644 --- a/scwx-qt/source/scwx/qt/map/marker_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/marker_layer.cpp @@ -57,10 +57,14 @@ void MarkerLayer::Impl::ReloadMarkers() for (size_t i = 0; i < markerManager->marker_count(); i++) { - const types::MarkerInfo& marker = markerManager->get_marker(i); + std::optional marker = markerManager->get_marker(i); + if (!marker) + { + break; + } std::shared_ptr icon = geoIcons_->AddIcon(); geoIcons_->SetIconTexture(icon, markerIconName_, 0); - geoIcons_->SetIconLocation(icon, marker.latitude, marker.longitude); + geoIcons_->SetIconLocation(icon, marker->latitude, marker->longitude); } geoIcons_->FinishIcons(); diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp index 3f137c8c..d5a4db1b 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.cpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.cpp @@ -87,15 +87,17 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const static const char COORDINATE_FORMAT = 'g'; static const int COORDINATE_PRECISION = 6; - if (!index.isValid() || index.row() < 0 || - static_cast(index.row()) >= - p->markerManager_->marker_count()) + if (!index.isValid() || index.row() < 0) { return QVariant(); } - const types::MarkerInfo markerInfo = + std::optional markerInfo = p->markerManager_->get_marker(index.row()); + if (!markerInfo) + { + return QVariant(); + } switch(index.column()) { @@ -104,7 +106,7 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const role == Qt::ItemDataRole::ToolTipRole || role == Qt::ItemDataRole::EditRole) { - return QString::fromStdString(markerInfo.name); + return QString::fromStdString(markerInfo->name); } break; @@ -114,7 +116,7 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const role == Qt::ItemDataRole::EditRole) { return QString::number( - markerInfo.latitude, COORDINATE_FORMAT, COORDINATE_PRECISION); + markerInfo->latitude, COORDINATE_FORMAT, COORDINATE_PRECISION); } break; @@ -124,7 +126,7 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const role == Qt::ItemDataRole::EditRole) { return QString::number( - markerInfo.longitude, COORDINATE_FORMAT, COORDINATE_PRECISION); + markerInfo->longitude, COORDINATE_FORMAT, COORDINATE_PRECISION); } break; @@ -167,14 +169,16 @@ bool MarkerModel::setData(const QModelIndex& index, const QVariant& value, int role) { - if (!index.isValid() || index.row() < 0 || - static_cast(index.row()) >= - p->markerManager_->marker_count()) + if (!index.isValid() || index.row() < 0) + { + return false; + } + std::optional markerInfo = + p->markerManager_->get_marker(index.row()); + if (!markerInfo) { return false; } - - types::MarkerInfo markerInfo = p->markerManager_->get_marker(index.row()); bool result = false; switch(index.column()) @@ -183,8 +187,8 @@ bool MarkerModel::setData(const QModelIndex& index, if (role == Qt::ItemDataRole::EditRole) { QString str = value.toString(); - markerInfo.name = str.toStdString(); - p->markerManager_->set_marker(index.row(), markerInfo); + markerInfo->name = str.toStdString(); + p->markerManager_->set_marker(index.row(), *markerInfo); result = true; } break; @@ -195,16 +199,10 @@ bool MarkerModel::setData(const QModelIndex& index, QString str = value.toString(); bool ok; double latitude = str.toDouble(&ok); - if (str.isEmpty()) + if (ok && str.isEmpty() && -90 <= latitude && latitude <= 90) { - markerInfo.latitude = 0; - p->markerManager_->set_marker(index.row(), markerInfo); - result = true; - } - else if (ok) - { - markerInfo.latitude = latitude; - p->markerManager_->set_marker(index.row(), markerInfo); + markerInfo->latitude = latitude; + p->markerManager_->set_marker(index.row(), *markerInfo); result = true; } } @@ -216,16 +214,10 @@ bool MarkerModel::setData(const QModelIndex& index, QString str = value.toString(); bool ok; double longitude = str.toDouble(&ok); - if (str.isEmpty()) + if (str.isEmpty() && ok && -180 <= longitude && longitude <= 180) { - markerInfo.longitude = 0; - p->markerManager_->set_marker(index.row(), markerInfo); - result = true; - } - else if (ok) - { - markerInfo.longitude = longitude; - p->markerManager_->set_marker(index.row(), markerInfo); + markerInfo->longitude = longitude; + p->markerManager_->set_marker(index.row(), *markerInfo); result = true; } } From 3b8e0d8180eb2362ccdb75f3d8d942c2a34395ea Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sun, 6 Oct 2024 12:55:21 -0400 Subject: [PATCH 21/30] update to propery check if string is empty --- scwx-qt/source/scwx/qt/model/marker_model.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp index d5a4db1b..04a65623 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.cpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.cpp @@ -199,7 +199,7 @@ bool MarkerModel::setData(const QModelIndex& index, QString str = value.toString(); bool ok; double latitude = str.toDouble(&ok); - if (ok && str.isEmpty() && -90 <= latitude && latitude <= 90) + if (!str.isEmpty() && ok && -90 <= latitude && latitude <= 90) { markerInfo->latitude = latitude; p->markerManager_->set_marker(index.row(), *markerInfo); @@ -214,7 +214,7 @@ bool MarkerModel::setData(const QModelIndex& index, QString str = value.toString(); bool ok; double longitude = str.toDouble(&ok); - if (str.isEmpty() && ok && -180 <= longitude && longitude <= 180) + if (!str.isEmpty() && ok && -180 <= longitude && longitude <= 180) { markerInfo->longitude = longitude; p->markerManager_->set_marker(index.row(), *markerInfo); From aabf4fcbb0a0b141a890d64b682d385b69bd31fa Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Sun, 6 Oct 2024 13:15:20 -0400 Subject: [PATCH 22/30] Updated marker to a custom marker so it is different from the center marker --- scwx-qt/res/textures/images/location-marker.svg | 9 +++++++++ scwx-qt/scwx-qt.qrc | 1 + scwx-qt/source/scwx/qt/map/marker_layer.cpp | 2 +- scwx-qt/source/scwx/qt/types/texture_types.cpp | 2 ++ scwx-qt/source/scwx/qt/types/texture_types.hpp | 1 + 5 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 scwx-qt/res/textures/images/location-marker.svg diff --git a/scwx-qt/res/textures/images/location-marker.svg b/scwx-qt/res/textures/images/location-marker.svg new file mode 100644 index 00000000..055c0bf0 --- /dev/null +++ b/scwx-qt/res/textures/images/location-marker.svg @@ -0,0 +1,9 @@ + + + + + diff --git a/scwx-qt/scwx-qt.qrc b/scwx-qt/scwx-qt.qrc index c9e00337..9ed5651a 100644 --- a/scwx-qt/scwx-qt.qrc +++ b/scwx-qt/scwx-qt.qrc @@ -75,6 +75,7 @@ res/textures/images/cursor-17.png res/textures/images/crosshairs-24.png res/textures/images/dot-3.png + res/textures/images/location-marker.svg res/textures/images/mapbox-logo.svg res/textures/images/maptiler-logo.svg diff --git a/scwx-qt/source/scwx/qt/map/marker_layer.cpp b/scwx-qt/source/scwx/qt/map/marker_layer.cpp index 545b6c32..5e8b6c61 100644 --- a/scwx-qt/source/scwx/qt/map/marker_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/marker_layer.cpp @@ -30,7 +30,7 @@ public: MarkerLayer* self_; const std::string& markerIconName_ { - types::GetTextureName(types::ImageTexture::Cursor17)}; + types::GetTextureName(types::ImageTexture::LocationMarker)}; std::shared_ptr geoIcons_; }; diff --git a/scwx-qt/source/scwx/qt/types/texture_types.cpp b/scwx-qt/source/scwx/qt/types/texture_types.cpp index 5f7da52b..7f0c7a24 100644 --- a/scwx-qt/source/scwx/qt/types/texture_types.cpp +++ b/scwx-qt/source/scwx/qt/types/texture_types.cpp @@ -25,6 +25,8 @@ static const std::unordered_map imageTextureInfo_ { {ImageTexture::Cursor17, {"images/cursor-17", ":/res/textures/images/cursor-17.png"}}, {ImageTexture::Dot3, {"images/dot-3", ":/res/textures/images/dot-3.png"}}, + {ImageTexture::LocationMarker, + {"images/location-marker", ":/res/textures/images/location-marker.svg"}}, {ImageTexture::MapboxLogo, {"images/mapbox-logo", ":/res/textures/images/mapbox-logo.svg"}}, {ImageTexture::MapTilerLogo, diff --git a/scwx-qt/source/scwx/qt/types/texture_types.hpp b/scwx-qt/source/scwx/qt/types/texture_types.hpp index 593d574d..307a7638 100644 --- a/scwx-qt/source/scwx/qt/types/texture_types.hpp +++ b/scwx-qt/source/scwx/qt/types/texture_types.hpp @@ -18,6 +18,7 @@ enum class ImageTexture Crosshairs24, Cursor17, Dot3, + LocationMarker, MapboxLogo, MapTilerLogo }; From aec937aa97f07433f77d286ac6a6b8ebf508658b Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Thu, 10 Oct 2024 08:38:33 -0400 Subject: [PATCH 23/30] add more handling to ensure that MarkerModel stays up to date with MarkerManager --- .../source/scwx/qt/manager/marker_manager.cpp | 3 ++ .../source/scwx/qt/manager/marker_manager.hpp | 2 ++ scwx-qt/source/scwx/qt/model/marker_model.cpp | 31 +++++++++++++++++++ scwx-qt/source/scwx/qt/model/marker_model.hpp | 2 ++ 4 files changed, 38 insertions(+) diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp index d74fe09f..19aa6a94 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp @@ -181,6 +181,8 @@ MarkerManager::MarkerManager() : p(std::make_unique(this)) // Read Marker settings on startup main::Application::WaitForInitialization(); p->ReadMarkerSettings(); + + Q_EMIT MarkersInitialized(p->markerRecords_.size()); } catch (const std::exception& ex) { @@ -219,6 +221,7 @@ void MarkerManager::set_marker(size_t index, const types::MarkerInfo& marker) std::shared_ptr& markerRecord = p->markerRecords_[index]; markerRecord->markerInfo_ = marker; + Q_EMIT MarkerChanged(index); Q_EMIT MarkersUpdated(); } diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp index 4fb81457..2f073ab7 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.hpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.hpp @@ -30,7 +30,9 @@ public: static std::shared_ptr Instance(); signals: + void MarkersInitialized(size_t count); void MarkersUpdated(); + void MarkerChanged(size_t index); void MarkerAdded(); void MarkerRemoved(size_t index); diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp index 04a65623..5ad00a56 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.cpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.cpp @@ -38,11 +38,22 @@ public: MarkerModel::MarkerModel(QObject* parent) : QAbstractTableModel(parent), p(std::make_unique()) { + + connect(p->markerManager_.get(), + &manager::MarkerManager::MarkersInitialized, + this, + &MarkerModel::HandleMarkersInitialized); + connect(p->markerManager_.get(), &manager::MarkerManager::MarkerAdded, this, &MarkerModel::HandleMarkerAdded); + connect(p->markerManager_.get(), + &manager::MarkerManager::MarkerChanged, + this, + &MarkerModel::HandleMarkerChanged); + connect(p->markerManager_.get(), &manager::MarkerManager::MarkerRemoved, this, @@ -235,6 +246,17 @@ bool MarkerModel::setData(const QModelIndex& index, return result; } +void MarkerModel::HandleMarkersInitialized(size_t count) +{ + QModelIndex topLeft = createIndex(0, kFirstColumn); + QModelIndex bottomRight = createIndex(count - 1, kLastColumn); + + beginInsertRows(QModelIndex(), 0, count - 1); + endInsertRows(); + + Q_EMIT dataChanged(topLeft, bottomRight); +} + void MarkerModel::HandleMarkerAdded() { const int newIndex = static_cast(p->markerManager_->marker_count() - 1); @@ -247,6 +269,15 @@ void MarkerModel::HandleMarkerAdded() Q_EMIT dataChanged(topLeft, bottomRight); } +void MarkerModel::HandleMarkerChanged(size_t index) +{ + const int changedIndex = static_cast(index); + QModelIndex topLeft = createIndex(changedIndex, kFirstColumn); + QModelIndex bottomRight = createIndex(changedIndex, kLastColumn); + + Q_EMIT dataChanged(topLeft, bottomRight); +} + void MarkerModel::HandleMarkerRemoved(size_t index) { const int removedIndex = static_cast(index); diff --git a/scwx-qt/source/scwx/qt/model/marker_model.hpp b/scwx-qt/source/scwx/qt/model/marker_model.hpp index 9c640238..c93526b1 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.hpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.hpp @@ -39,7 +39,9 @@ public: public slots: + void HandleMarkersInitialized(size_t count); void HandleMarkerAdded(); + void HandleMarkerChanged(size_t index); void HandleMarkerRemoved(size_t index); private: From 0c20e49831b322fc8b2dda7519e0e505fbee4f7c Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Thu, 10 Oct 2024 09:43:16 -0400 Subject: [PATCH 24/30] Moved name to end of model to make it take all remaining space --- scwx-qt/source/scwx/qt/model/marker_model.cpp | 8 ++------ scwx-qt/source/scwx/qt/model/marker_model.hpp | 6 +++--- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp index 5ad00a56..ed8c67dc 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.cpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.cpp @@ -5,10 +5,6 @@ #include #include -#include -#include -#include -#include namespace scwx { @@ -21,9 +17,9 @@ static const std::string logPrefix_ = "scwx::qt::model::marker_model"; static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static constexpr int kFirstColumn = - static_cast(MarkerModel::Column::Name); + static_cast(MarkerModel::Column::Latitude); static constexpr int kLastColumn = - static_cast(MarkerModel::Column::Longitude); + static_cast(MarkerModel::Column::Name); static constexpr int kNumColumns = kLastColumn - kFirstColumn + 1; class MarkerModel::Impl diff --git a/scwx-qt/source/scwx/qt/model/marker_model.hpp b/scwx-qt/source/scwx/qt/model/marker_model.hpp index c93526b1..85112fa1 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.hpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.hpp @@ -14,9 +14,9 @@ class MarkerModel : public QAbstractTableModel public: enum class Column : int { - Name = 0, - Latitude = 1, - Longitude = 2 + Latitude = 0, + Longitude = 1, + Name = 2, }; explicit MarkerModel(QObject* parent = nullptr); From 60a059078c98d6d1427cbf05e6929f18e417571d Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Thu, 10 Oct 2024 11:00:32 -0400 Subject: [PATCH 25/30] fixed missing static cast on size_t to int convertion --- scwx-qt/source/scwx/qt/model/marker_model.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp index ed8c67dc..9a046954 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.cpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.cpp @@ -244,10 +244,11 @@ bool MarkerModel::setData(const QModelIndex& index, void MarkerModel::HandleMarkersInitialized(size_t count) { + const int index = static_cast(count - 1); QModelIndex topLeft = createIndex(0, kFirstColumn); - QModelIndex bottomRight = createIndex(count - 1, kLastColumn); + QModelIndex bottomRight = createIndex(index, kLastColumn); - beginInsertRows(QModelIndex(), 0, count - 1); + beginInsertRows(QModelIndex(), 0, index); endInsertRows(); Q_EMIT dataChanged(topLeft, bottomRight); From 78b453249a445ee7864adbe02ab6e864abcb8fb0 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Fri, 11 Oct 2024 11:03:36 -0400 Subject: [PATCH 26/30] Change cordinates to be displayed in a consistent format --- scwx-qt/source/scwx/qt/model/marker_model.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp index 9a046954..3ea77ecc 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.cpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -92,7 +93,7 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const { static const char COORDINATE_FORMAT = 'g'; - static const int COORDINATE_PRECISION = 6; + static const int COORDINATE_PRECISION = 10; if (!index.isValid() || index.row() < 0) { @@ -119,8 +120,12 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const case static_cast(Column::Latitude): if (role == Qt::ItemDataRole::DisplayRole || - role == Qt::ItemDataRole::ToolTipRole || - role == Qt::ItemDataRole::EditRole) + role == Qt::ItemDataRole::ToolTipRole) + { + return QString::fromStdString( + common::GetLatitudeString(markerInfo->latitude)); + } + else if (role == Qt::ItemDataRole::EditRole) { return QString::number( markerInfo->latitude, COORDINATE_FORMAT, COORDINATE_PRECISION); @@ -129,13 +134,18 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const case static_cast(Column::Longitude): if (role == Qt::ItemDataRole::DisplayRole || - role == Qt::ItemDataRole::ToolTipRole || - role == Qt::ItemDataRole::EditRole) + role == Qt::ItemDataRole::ToolTipRole) + { + return QString::fromStdString( + common::GetLongitudeString(markerInfo->longitude)); + } + else if (role == Qt::ItemDataRole::EditRole) { return QString::number( markerInfo->longitude, COORDINATE_FORMAT, COORDINATE_PRECISION); } break; + break; default: break; From a8845514c65cc932a0176abfae2b1a06f730dcd5 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Thu, 17 Oct 2024 16:43:00 -0400 Subject: [PATCH 27/30] Updated SVG to be much closer to an equilateral triangle --- scwx-qt/res/textures/images/location-marker.svg | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/scwx-qt/res/textures/images/location-marker.svg b/scwx-qt/res/textures/images/location-marker.svg index 055c0bf0..8ebb064f 100644 --- a/scwx-qt/res/textures/images/location-marker.svg +++ b/scwx-qt/res/textures/images/location-marker.svg @@ -1,9 +1,11 @@ - - + + + From ee998232f7ae78a384977b63b5f2d32f2eb210fa Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Thu, 17 Oct 2024 17:50:17 -0400 Subject: [PATCH 28/30] Add mutexes to marker manager --- .../source/scwx/qt/manager/marker_manager.cpp | 127 ++++++++++-------- 1 file changed, 73 insertions(+), 54 deletions(-) diff --git a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp index 19aa6a94..382aafd7 100644 --- a/scwx-qt/source/scwx/qt/manager/marker_manager.cpp +++ b/scwx-qt/source/scwx/qt/manager/marker_manager.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -41,6 +42,7 @@ public: MarkerManager* self_; boost::asio::thread_pool threadPool_ {1u}; + std::shared_mutex markerRecordLock_ {}; void InitializeMarkerSettings(); void ReadMarkerSettings(); @@ -109,38 +111,41 @@ void MarkerManager::Impl::ReadMarkerSettings() logger_->info("Reading location marker settings"); boost::json::value markerJson = nullptr; - - // Determine if marker settings exists - if (std::filesystem::exists(markerSettingsPath_)) { - markerJson = util::json::ReadJsonFile(markerSettingsPath_); - } + std::unique_lock lock(markerRecordLock_); - if (markerJson != nullptr && markerJson.is_array()) - { - // For each marker entry - auto& markerArray = markerJson.as_array(); - markerRecords_.reserve(markerArray.size()); - for (auto& markerEntry : markerArray) + // Determine if marker settings exists + if (std::filesystem::exists(markerSettingsPath_)) { - try - { - MarkerRecord record = - boost::json::value_to(markerEntry); - - if (!record.markerInfo_.name.empty()) - { - markerRecords_.emplace_back( - std::make_shared(record.markerInfo_)); - } - } - catch (const std::exception& ex) - { - logger_->warn("Invalid location marker entry: {}", ex.what()); - } + markerJson = util::json::ReadJsonFile(markerSettingsPath_); } - logger_->debug("{} location marker entries", markerRecords_.size()); + if (markerJson != nullptr && markerJson.is_array()) + { + // For each marker entry + auto& markerArray = markerJson.as_array(); + markerRecords_.reserve(markerArray.size()); + for (auto& markerEntry : markerArray) + { + try + { + MarkerRecord record = + boost::json::value_to(markerEntry); + + if (!record.markerInfo_.name.empty()) + { + markerRecords_.emplace_back( + std::make_shared(record.markerInfo_)); + } + } + catch (const std::exception& ex) + { + logger_->warn("Invalid location marker entry: {}", ex.what()); + } + } + + logger_->debug("{} location marker entries", markerRecords_.size()); + } } Q_EMIT self_->MarkersUpdated(); @@ -150,6 +155,7 @@ void MarkerManager::Impl::WriteMarkerSettings() { logger_->info("Saving location marker settings"); + std::shared_lock lock(markerRecordLock_); auto markerJson = boost::json::value_from(markerRecords_); util::json::WriteJsonFile(markerSettingsPath_, markerJson); } @@ -203,6 +209,7 @@ size_t MarkerManager::marker_count() std::optional MarkerManager::get_marker(size_t index) { + std::shared_lock lock(p->markerRecordLock_); if (index >= p->markerRecords_.size()) { return {}; @@ -214,32 +221,41 @@ std::optional MarkerManager::get_marker(size_t index) void MarkerManager::set_marker(size_t index, const types::MarkerInfo& marker) { - if (index >= p->markerRecords_.size()) { - return; + std::unique_lock lock(p->markerRecordLock_); + if (index >= p->markerRecords_.size()) + { + return; + } + std::shared_ptr& markerRecord = + p->markerRecords_[index]; + markerRecord->markerInfo_ = marker; } - std::shared_ptr& markerRecord = - p->markerRecords_[index]; - markerRecord->markerInfo_ = marker; Q_EMIT MarkerChanged(index); Q_EMIT MarkersUpdated(); } void MarkerManager::add_marker(const types::MarkerInfo& marker) { - p->markerRecords_.emplace_back(std::make_shared(marker)); + { + std::unique_lock lock(p->markerRecordLock_); + p->markerRecords_.emplace_back(std::make_shared(marker)); + } Q_EMIT MarkerAdded(); Q_EMIT MarkersUpdated(); } void MarkerManager::remove_marker(size_t index) { - if (index >= p->markerRecords_.size()) { - return; - } + std::unique_lock lock(p->markerRecordLock_); + if (index >= p->markerRecords_.size()) + { + return; + } - p->markerRecords_.erase(std::next(p->markerRecords_.begin(), index)); + p->markerRecords_.erase(std::next(p->markerRecords_.begin(), index)); + } Q_EMIT MarkerRemoved(index); Q_EMIT MarkersUpdated(); @@ -247,29 +263,32 @@ void MarkerManager::remove_marker(size_t index) void MarkerManager::move_marker(size_t from, size_t to) { - if (from >= p->markerRecords_.size() || to >= p->markerRecords_.size()) { - return; - } - std::shared_ptr& markerRecord = - p->markerRecords_[from]; + std::unique_lock lock(p->markerRecordLock_); + if (from >= p->markerRecords_.size() || to >= p->markerRecords_.size()) + { + return; + } + std::shared_ptr& markerRecord = + p->markerRecords_[from]; - if (from == to) {} - else if (from < to) - { - for (size_t i = from; i < to; i++) + if (from == to) {} + else if (from < to) { - p->markerRecords_[i] = p->markerRecords_[i + 1]; + for (size_t i = from; i < to; i++) + { + p->markerRecords_[i] = p->markerRecords_[i + 1]; + } + p->markerRecords_[to] = markerRecord; } - p->markerRecords_[to] = markerRecord; - } - else - { - for (size_t i = from; i > to; i--) + else { - p->markerRecords_[i] = p->markerRecords_[i - 1]; + for (size_t i = from; i > to; i--) + { + p->markerRecords_[i] = p->markerRecords_[i - 1]; + } + p->markerRecords_[to] = markerRecord; } - p->markerRecords_[to] = markerRecord; } Q_EMIT MarkersUpdated(); } From a82e379f9b86be2ee0436a7ba3fbf382f0c2cf37 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Thu, 17 Oct 2024 17:52:00 -0400 Subject: [PATCH 29/30] Make marker layer emit NeedsRendering on updating markers --- scwx-qt/source/scwx/qt/map/marker_layer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/scwx-qt/source/scwx/qt/map/marker_layer.cpp b/scwx-qt/source/scwx/qt/map/marker_layer.cpp index 5e8b6c61..ab97322f 100644 --- a/scwx-qt/source/scwx/qt/map/marker_layer.cpp +++ b/scwx-qt/source/scwx/qt/map/marker_layer.cpp @@ -68,6 +68,7 @@ void MarkerLayer::Impl::ReloadMarkers() } geoIcons_->FinishIcons(); + Q_EMIT self_->NeedsRendering(); } MarkerLayer::MarkerLayer(const std::shared_ptr& context) : From fe9311325b4897a504a95174624dfcf7cf3a40d1 Mon Sep 17 00:00:00 2001 From: AdenKoperczak Date: Thu, 17 Oct 2024 17:55:45 -0400 Subject: [PATCH 30/30] removed unneded dataChanged calls in MarkerModel --- scwx-qt/source/scwx/qt/model/marker_model.cpp | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/scwx-qt/source/scwx/qt/model/marker_model.cpp b/scwx-qt/source/scwx/qt/model/marker_model.cpp index 3ea77ecc..eb3e8bee 100644 --- a/scwx-qt/source/scwx/qt/model/marker_model.cpp +++ b/scwx-qt/source/scwx/qt/model/marker_model.cpp @@ -255,25 +255,17 @@ bool MarkerModel::setData(const QModelIndex& index, void MarkerModel::HandleMarkersInitialized(size_t count) { const int index = static_cast(count - 1); - QModelIndex topLeft = createIndex(0, kFirstColumn); - QModelIndex bottomRight = createIndex(index, kLastColumn); beginInsertRows(QModelIndex(), 0, index); endInsertRows(); - - Q_EMIT dataChanged(topLeft, bottomRight); } void MarkerModel::HandleMarkerAdded() { const int newIndex = static_cast(p->markerManager_->marker_count() - 1); - QModelIndex topLeft = createIndex(newIndex, kFirstColumn); - QModelIndex bottomRight = createIndex(newIndex, kLastColumn); beginInsertRows(QModelIndex(), newIndex, newIndex); endInsertRows(); - - Q_EMIT dataChanged(topLeft, bottomRight); } void MarkerModel::HandleMarkerChanged(size_t index) @@ -288,13 +280,9 @@ void MarkerModel::HandleMarkerChanged(size_t index) void MarkerModel::HandleMarkerRemoved(size_t index) { const int removedIndex = static_cast(index); - QModelIndex topLeft = createIndex(removedIndex, kFirstColumn); - QModelIndex bottomRight = createIndex(removedIndex, kLastColumn); beginRemoveRows(QModelIndex(), removedIndex, removedIndex); endRemoveRows(); - - Q_EMIT dataChanged(topLeft, bottomRight); } } // namespace model