mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 16:50:06 +00:00 
			
		
		
		
	Merge pull request #281 from AdenKoperczak/location_markers
Add Location Markers (Part 1)
This commit is contained in:
		
						commit
						1843f387ff
					
				
					 25 changed files with 1343 additions and 3 deletions
				
			
		
							
								
								
									
										11
									
								
								scwx-qt/res/textures/images/location-marker.svg
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								scwx-qt/res/textures/images/location-marker.svg
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | <svg version="1.1" | ||||||
|  |      viewBox="0 0 170 150" | ||||||
|  |      width="17" height="15" | ||||||
|  |      xmlns="http://www.w3.org/2000/svg"> | ||||||
|  | 
 | ||||||
|  |     <path d="M 40,118 L 85,40 L 130,118 L 40,118 L 85,40 Z" | ||||||
|  |         stroke="black" stroke-width="40" fill="none"/> | ||||||
|  |     <path d="M 40,118 L 85,40 L 130,118 L 40,118 L 85,40 Z" | ||||||
|  |         stroke="red"   stroke-width="20" fill="none"/> | ||||||
|  | 
 | ||||||
|  |  </svg> | ||||||
| After Width: | Height: | Size: 355 B | 
|  | @ -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/log_manager.hpp | ||||||
|                 source/scwx/qt/manager/media_manager.hpp |                 source/scwx/qt/manager/media_manager.hpp | ||||||
|                 source/scwx/qt/manager/placefile_manager.hpp |                 source/scwx/qt/manager/placefile_manager.hpp | ||||||
|  |                 source/scwx/qt/manager/marker_manager.hpp | ||||||
|                 source/scwx/qt/manager/position_manager.hpp |                 source/scwx/qt/manager/position_manager.hpp | ||||||
|                 source/scwx/qt/manager/radar_product_manager.hpp |                 source/scwx/qt/manager/radar_product_manager.hpp | ||||||
|                 source/scwx/qt/manager/radar_product_manager_notifier.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/log_manager.cpp | ||||||
|                 source/scwx/qt/manager/media_manager.cpp |                 source/scwx/qt/manager/media_manager.cpp | ||||||
|                 source/scwx/qt/manager/placefile_manager.cpp |                 source/scwx/qt/manager/placefile_manager.cpp | ||||||
|  |                 source/scwx/qt/manager/marker_manager.cpp | ||||||
|                 source/scwx/qt/manager/position_manager.cpp |                 source/scwx/qt/manager/position_manager.cpp | ||||||
|                 source/scwx/qt/manager/radar_product_manager.cpp |                 source/scwx/qt/manager/radar_product_manager.cpp | ||||||
|                 source/scwx/qt/manager/radar_product_manager_notifier.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_layer.hpp | ||||||
|             source/scwx/qt/map/overlay_product_layer.hpp |             source/scwx/qt/map/overlay_product_layer.hpp | ||||||
|             source/scwx/qt/map/placefile_layer.hpp |             source/scwx/qt/map/placefile_layer.hpp | ||||||
|  |             source/scwx/qt/map/marker_layer.hpp | ||||||
|             source/scwx/qt/map/radar_product_layer.hpp |             source/scwx/qt/map/radar_product_layer.hpp | ||||||
|             source/scwx/qt/map/radar_range_layer.hpp |             source/scwx/qt/map/radar_range_layer.hpp | ||||||
|             source/scwx/qt/map/radar_site_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_layer.cpp | ||||||
|             source/scwx/qt/map/overlay_product_layer.cpp |             source/scwx/qt/map/overlay_product_layer.cpp | ||||||
|             source/scwx/qt/map/placefile_layer.cpp |             source/scwx/qt/map/placefile_layer.cpp | ||||||
|  |             source/scwx/qt/map/marker_layer.cpp | ||||||
|             source/scwx/qt/map/radar_product_layer.cpp |             source/scwx/qt/map/radar_product_layer.cpp | ||||||
|             source/scwx/qt/map/radar_range_layer.cpp |             source/scwx/qt/map/radar_range_layer.cpp | ||||||
|             source/scwx/qt/map/radar_site_layer.cpp) |             source/scwx/qt/map/radar_site_layer.cpp) | ||||||
|  | @ -154,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/imgui_context_model.hpp | ||||||
|               source/scwx/qt/model/layer_model.hpp |               source/scwx/qt/model/layer_model.hpp | ||||||
|               source/scwx/qt/model/placefile_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/radar_site_model.hpp | ||||||
|               source/scwx/qt/model/tree_item.hpp |               source/scwx/qt/model/tree_item.hpp | ||||||
|               source/scwx/qt/model/tree_model.hpp) |               source/scwx/qt/model/tree_model.hpp) | ||||||
|  | @ -162,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/imgui_context_model.cpp | ||||||
|               source/scwx/qt/model/layer_model.cpp |               source/scwx/qt/model/layer_model.cpp | ||||||
|               source/scwx/qt/model/placefile_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/radar_site_model.cpp | ||||||
|               source/scwx/qt/model/tree_item.cpp |               source/scwx/qt/model/tree_item.cpp | ||||||
|               source/scwx/qt/model/tree_model.cpp) |               source/scwx/qt/model/tree_model.cpp) | ||||||
|  | @ -215,6 +221,7 @@ set(HDR_TYPES source/scwx/qt/types/alert_types.hpp | ||||||
|               source/scwx/qt/types/location_types.hpp |               source/scwx/qt/types/location_types.hpp | ||||||
|               source/scwx/qt/types/map_types.hpp |               source/scwx/qt/types/map_types.hpp | ||||||
|               source/scwx/qt/types/media_types.hpp |               source/scwx/qt/types/media_types.hpp | ||||||
|  |               source/scwx/qt/types/marker_types.hpp | ||||||
|               source/scwx/qt/types/qt_types.hpp |               source/scwx/qt/types/qt_types.hpp | ||||||
|               source/scwx/qt/types/radar_product_record.hpp |               source/scwx/qt/types/radar_product_record.hpp | ||||||
|               source/scwx/qt/types/text_event_key.hpp |               source/scwx/qt/types/text_event_key.hpp | ||||||
|  | @ -260,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/open_url_dialog.hpp | ||||||
|            source/scwx/qt/ui/placefile_dialog.hpp |            source/scwx/qt/ui/placefile_dialog.hpp | ||||||
|            source/scwx/qt/ui/placefile_settings_widget.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/progress_dialog.hpp | ||||||
|            source/scwx/qt/ui/radar_site_dialog.hpp |            source/scwx/qt/ui/radar_site_dialog.hpp | ||||||
|            source/scwx/qt/ui/serial_port_dialog.hpp |            source/scwx/qt/ui/serial_port_dialog.hpp | ||||||
|  | @ -288,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/open_url_dialog.cpp | ||||||
|            source/scwx/qt/ui/placefile_dialog.cpp |            source/scwx/qt/ui/placefile_dialog.cpp | ||||||
|            source/scwx/qt/ui/placefile_settings_widget.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/progress_dialog.cpp | ||||||
|            source/scwx/qt/ui/radar_site_dialog.cpp |            source/scwx/qt/ui/radar_site_dialog.cpp | ||||||
|            source/scwx/qt/ui/settings_dialog.cpp |            source/scwx/qt/ui/settings_dialog.cpp | ||||||
|  | @ -307,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/open_url_dialog.ui | ||||||
|            source/scwx/qt/ui/placefile_dialog.ui |            source/scwx/qt/ui/placefile_dialog.ui | ||||||
|            source/scwx/qt/ui/placefile_settings_widget.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/progress_dialog.ui | ||||||
|            source/scwx/qt/ui/radar_site_dialog.ui |            source/scwx/qt/ui/radar_site_dialog.ui | ||||||
|            source/scwx/qt/ui/settings_dialog.ui |            source/scwx/qt/ui/settings_dialog.ui | ||||||
|  |  | ||||||
|  | @ -75,6 +75,7 @@ | ||||||
|         <file>res/textures/images/cursor-17.png</file> |         <file>res/textures/images/cursor-17.png</file> | ||||||
|         <file>res/textures/images/crosshairs-24.png</file> |         <file>res/textures/images/crosshairs-24.png</file> | ||||||
|         <file>res/textures/images/dot-3.png</file> |         <file>res/textures/images/dot-3.png</file> | ||||||
|  |         <file>res/textures/images/location-marker.svg</file> | ||||||
|         <file>res/textures/images/mapbox-logo.svg</file> |         <file>res/textures/images/mapbox-logo.svg</file> | ||||||
|         <file>res/textures/images/maptiler-logo.svg</file> |         <file>res/textures/images/maptiler-logo.svg</file> | ||||||
|     </qresource> |     </qresource> | ||||||
|  |  | ||||||
|  | @ -6,6 +6,7 @@ | ||||||
| #include <scwx/qt/manager/alert_manager.hpp> | #include <scwx/qt/manager/alert_manager.hpp> | ||||||
| #include <scwx/qt/manager/hotkey_manager.hpp> | #include <scwx/qt/manager/hotkey_manager.hpp> | ||||||
| #include <scwx/qt/manager/placefile_manager.hpp> | #include <scwx/qt/manager/placefile_manager.hpp> | ||||||
|  | #include <scwx/qt/manager/marker_manager.hpp> | ||||||
| #include <scwx/qt/manager/position_manager.hpp> | #include <scwx/qt/manager/position_manager.hpp> | ||||||
| #include <scwx/qt/manager/radar_product_manager.hpp> | #include <scwx/qt/manager/radar_product_manager.hpp> | ||||||
| #include <scwx/qt/manager/text_event_manager.hpp> | #include <scwx/qt/manager/text_event_manager.hpp> | ||||||
|  | @ -30,6 +31,7 @@ | ||||||
| #include <scwx/qt/ui/level2_settings_widget.hpp> | #include <scwx/qt/ui/level2_settings_widget.hpp> | ||||||
| #include <scwx/qt/ui/level3_products_widget.hpp> | #include <scwx/qt/ui/level3_products_widget.hpp> | ||||||
| #include <scwx/qt/ui/placefile_dialog.hpp> | #include <scwx/qt/ui/placefile_dialog.hpp> | ||||||
|  | #include <scwx/qt/ui/marker_dialog.hpp> | ||||||
| #include <scwx/qt/ui/radar_site_dialog.hpp> | #include <scwx/qt/ui/radar_site_dialog.hpp> | ||||||
| #include <scwx/qt/ui/settings_dialog.hpp> | #include <scwx/qt/ui/settings_dialog.hpp> | ||||||
| #include <scwx/qt/ui/update_dialog.hpp> | #include <scwx/qt/ui/update_dialog.hpp> | ||||||
|  | @ -86,11 +88,13 @@ public: | ||||||
|        imGuiDebugDialog_ {nullptr}, |        imGuiDebugDialog_ {nullptr}, | ||||||
|        layerDialog_ {nullptr}, |        layerDialog_ {nullptr}, | ||||||
|        placefileDialog_ {nullptr}, |        placefileDialog_ {nullptr}, | ||||||
|  |        markerDialog_ {nullptr}, | ||||||
|        radarSiteDialog_ {nullptr}, |        radarSiteDialog_ {nullptr}, | ||||||
|        settingsDialog_ {nullptr}, |        settingsDialog_ {nullptr}, | ||||||
|        updateDialog_ {nullptr}, |        updateDialog_ {nullptr}, | ||||||
|        alertManager_ {manager::AlertManager::Instance()}, |        alertManager_ {manager::AlertManager::Instance()}, | ||||||
|        placefileManager_ {manager::PlacefileManager::Instance()}, |        placefileManager_ {manager::PlacefileManager::Instance()}, | ||||||
|  |        markerManager_ {manager::MarkerManager::Instance()}, | ||||||
|        positionManager_ {manager::PositionManager::Instance()}, |        positionManager_ {manager::PositionManager::Instance()}, | ||||||
|        textEventManager_ {manager::TextEventManager::Instance()}, |        textEventManager_ {manager::TextEventManager::Instance()}, | ||||||
|        timelineManager_ {manager::TimelineManager::Instance()}, |        timelineManager_ {manager::TimelineManager::Instance()}, | ||||||
|  | @ -203,6 +207,7 @@ public: | ||||||
|    ui::ImGuiDebugDialog*    imGuiDebugDialog_; |    ui::ImGuiDebugDialog*    imGuiDebugDialog_; | ||||||
|    ui::LayerDialog*         layerDialog_; |    ui::LayerDialog*         layerDialog_; | ||||||
|    ui::PlacefileDialog*     placefileDialog_; |    ui::PlacefileDialog*     placefileDialog_; | ||||||
|  |    ui::MarkerDialog*        markerDialog_; | ||||||
|    ui::RadarSiteDialog*     radarSiteDialog_; |    ui::RadarSiteDialog*     radarSiteDialog_; | ||||||
|    ui::SettingsDialog*      settingsDialog_; |    ui::SettingsDialog*      settingsDialog_; | ||||||
|    ui::UpdateDialog*        updateDialog_; |    ui::UpdateDialog*        updateDialog_; | ||||||
|  | @ -217,6 +222,7 @@ public: | ||||||
|    std::shared_ptr<manager::HotkeyManager> hotkeyManager_ { |    std::shared_ptr<manager::HotkeyManager> hotkeyManager_ { | ||||||
|       manager::HotkeyManager::Instance()}; |       manager::HotkeyManager::Instance()}; | ||||||
|    std::shared_ptr<manager::PlacefileManager> placefileManager_; |    std::shared_ptr<manager::PlacefileManager> placefileManager_; | ||||||
|  |    std::shared_ptr<manager::MarkerManager>    markerManager_; | ||||||
|    std::shared_ptr<manager::PositionManager>  positionManager_; |    std::shared_ptr<manager::PositionManager>  positionManager_; | ||||||
|    std::shared_ptr<manager::TextEventManager> textEventManager_; |    std::shared_ptr<manager::TextEventManager> textEventManager_; | ||||||
|    std::shared_ptr<manager::TimelineManager>  timelineManager_; |    std::shared_ptr<manager::TimelineManager>  timelineManager_; | ||||||
|  | @ -303,6 +309,9 @@ MainWindow::MainWindow(QWidget* parent) : | ||||||
|    // Placefile Manager Dialog
 |    // Placefile Manager Dialog
 | ||||||
|    p->placefileDialog_ = new ui::PlacefileDialog(this); |    p->placefileDialog_ = new ui::PlacefileDialog(this); | ||||||
| 
 | 
 | ||||||
|  |    // Marker Manager Dialog
 | ||||||
|  |    p->markerDialog_ = new ui::MarkerDialog(this); | ||||||
|  | 
 | ||||||
|    // Layer Dialog
 |    // Layer Dialog
 | ||||||
|    p->layerDialog_ = new ui::LayerDialog(this); |    p->layerDialog_ = new ui::LayerDialog(this); | ||||||
| 
 | 
 | ||||||
|  | @ -610,6 +619,11 @@ void MainWindow::on_actionPlacefileManager_triggered() | ||||||
|    p->placefileDialog_->show(); |    p->placefileDialog_->show(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void MainWindow::on_actionMarkerManager_triggered() | ||||||
|  | { | ||||||
|  |    p->markerDialog_->show(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void MainWindow::on_actionLayerManager_triggered() | void MainWindow::on_actionLayerManager_triggered() | ||||||
| { | { | ||||||
|    p->layerDialog_->show(); |    p->layerDialog_->show(); | ||||||
|  |  | ||||||
|  | @ -44,6 +44,7 @@ private slots: | ||||||
|    void on_actionRadarRange_triggered(bool checked); |    void on_actionRadarRange_triggered(bool checked); | ||||||
|    void on_actionRadarSites_triggered(bool checked); |    void on_actionRadarSites_triggered(bool checked); | ||||||
|    void on_actionPlacefileManager_triggered(); |    void on_actionPlacefileManager_triggered(); | ||||||
|  |    void on_actionMarkerManager_triggered(); | ||||||
|    void on_actionLayerManager_triggered(); |    void on_actionLayerManager_triggered(); | ||||||
|    void on_actionImGuiDebug_triggered(); |    void on_actionImGuiDebug_triggered(); | ||||||
|    void on_actionDumpLayerList_triggered(); |    void on_actionDumpLayerList_triggered(); | ||||||
|  |  | ||||||
|  | @ -39,7 +39,7 @@ | ||||||
|      <x>0</x> |      <x>0</x> | ||||||
|      <y>0</y> |      <y>0</y> | ||||||
|      <width>1024</width> |      <width>1024</width> | ||||||
|      <height>33</height> |      <height>22</height> | ||||||
|     </rect> |     </rect> | ||||||
|    </property> |    </property> | ||||||
|    <widget class="QMenu" name="menuFile"> |    <widget class="QMenu" name="menuFile"> | ||||||
|  | @ -104,6 +104,7 @@ | ||||||
|     </property> |     </property> | ||||||
|     <addaction name="actionPlacefileManager"/> |     <addaction name="actionPlacefileManager"/> | ||||||
|     <addaction name="actionLayerManager"/> |     <addaction name="actionLayerManager"/> | ||||||
|  |     <addaction name="actionMarkerManager"/> | ||||||
|    </widget> |    </widget> | ||||||
|    <addaction name="menuFile"/> |    <addaction name="menuFile"/> | ||||||
|    <addaction name="menuView"/> |    <addaction name="menuView"/> | ||||||
|  | @ -152,8 +153,8 @@ | ||||||
|          <rect> |          <rect> | ||||||
|           <x>0</x> |           <x>0</x> | ||||||
|           <y>0</y> |           <y>0</y> | ||||||
|           <width>190</width> |           <width>205</width> | ||||||
|           <height>686</height> |           <height>701</height> | ||||||
|          </rect> |          </rect> | ||||||
|         </property> |         </property> | ||||||
|         <layout class="QVBoxLayout" name="verticalLayout_6"> |         <layout class="QVBoxLayout" name="verticalLayout_6"> | ||||||
|  | @ -487,6 +488,15 @@ | ||||||
|     <string>&GPS Info</string> |     <string>&GPS Info</string> | ||||||
|    </property> |    </property> | ||||||
|   </action> |   </action> | ||||||
|  |   <action name="actionMarkerManager"> | ||||||
|  |    <property name="icon"> | ||||||
|  |     <iconset resource="../../../../scwx-qt.qrc"> | ||||||
|  |      <normaloff>:/res/icons/font-awesome-6/house-solid.svg</normaloff>:/res/icons/font-awesome-6/house-solid.svg</iconset> | ||||||
|  |    </property> | ||||||
|  |    <property name="text"> | ||||||
|  |     <string>Location &Marker Manager</string> | ||||||
|  |    </property> | ||||||
|  |   </action> | ||||||
|  </widget> |  </widget> | ||||||
|  <resources> |  <resources> | ||||||
|   <include location="../../../../scwx-qt.qrc"/> |   <include location="../../../../scwx-qt.qrc"/> | ||||||
|  |  | ||||||
							
								
								
									
										317
									
								
								scwx-qt/source/scwx/qt/manager/marker_manager.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										317
									
								
								scwx-qt/source/scwx/qt/manager/marker_manager.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,317 @@ | ||||||
|  | #include <scwx/qt/manager/marker_manager.hpp> | ||||||
|  | #include <scwx/qt/types/marker_types.hpp> | ||||||
|  | #include <scwx/qt/util/json.hpp> | ||||||
|  | #include <scwx/qt/main/application.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
|  | 
 | ||||||
|  | #include <filesystem> | ||||||
|  | #include <shared_mutex> | ||||||
|  | #include <vector> | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | #include <QStandardPaths> | ||||||
|  | #include <boost/json.hpp> | ||||||
|  | #include <boost/asio/post.hpp> | ||||||
|  | #include <boost/asio/thread_pool.hpp> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace 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 MarkerManager::Impl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    class MarkerRecord; | ||||||
|  | 
 | ||||||
|  |    explicit Impl(MarkerManager* self) : self_ {self} {} | ||||||
|  |    ~Impl() { threadPool_.join(); } | ||||||
|  | 
 | ||||||
|  |    std::string                                markerSettingsPath_ {}; | ||||||
|  |    std::vector<std::shared_ptr<MarkerRecord>> markerRecords_ {}; | ||||||
|  | 
 | ||||||
|  |    MarkerManager* self_; | ||||||
|  | 
 | ||||||
|  |    boost::asio::thread_pool threadPool_ {1u}; | ||||||
|  |    std::shared_mutex        markerRecordLock_ {}; | ||||||
|  | 
 | ||||||
|  |    void                          InitializeMarkerSettings(); | ||||||
|  |    void                          ReadMarkerSettings(); | ||||||
|  |    void                          WriteMarkerSettings(); | ||||||
|  |    std::shared_ptr<MarkerRecord> GetMarkerByName(const std::string& name); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class MarkerManager::Impl::MarkerRecord | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    MarkerRecord(const std::string& name, double latitude, double longitude) : | ||||||
|  |       markerInfo_ {types::MarkerInfo(name, latitude, longitude)} | ||||||
|  |    { | ||||||
|  |    } | ||||||
|  |    MarkerRecord(const types::MarkerInfo& info) : | ||||||
|  |       markerInfo_ {info} | ||||||
|  |    { | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    const 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<MarkerRecord>& record) | ||||||
|  |    { | ||||||
|  |       jv = {{kNameName_, record->markerInfo_.name}, | ||||||
|  |             {kLatitudeName_, record->markerInfo_.latitude}, | ||||||
|  |             {kLongitudeName_, record->markerInfo_.longitude}}; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    friend MarkerRecord tag_invoke(boost::json::value_to_tag<MarkerRecord>, | ||||||
|  |                                   const boost::json::value& jv) | ||||||
|  |    { | ||||||
|  |       return MarkerRecord( | ||||||
|  |          boost::json::value_to<std::string>(jv.at(kNameName_)), | ||||||
|  |          boost::json::value_to<double>(jv.at(kLatitudeName_)), | ||||||
|  |          boost::json::value_to<double>(jv.at(kLongitudeName_))); | ||||||
|  |    } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void MarkerManager::Impl::InitializeMarkerSettings() | ||||||
|  | { | ||||||
|  |    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); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    markerSettingsPath_ = appDataPath + "/location-markers.json"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MarkerManager::Impl::ReadMarkerSettings() | ||||||
|  | { | ||||||
|  |    logger_->info("Reading location marker settings"); | ||||||
|  | 
 | ||||||
|  |    boost::json::value markerJson = nullptr; | ||||||
|  |    { | ||||||
|  |       std::unique_lock lock(markerRecordLock_); | ||||||
|  | 
 | ||||||
|  |       // Determine if marker settings exists
 | ||||||
|  |       if (std::filesystem::exists(markerSettingsPath_)) | ||||||
|  |       { | ||||||
|  |          markerJson = util::json::ReadJsonFile(markerSettingsPath_); | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       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<MarkerRecord>(markerEntry); | ||||||
|  | 
 | ||||||
|  |                if (!record.markerInfo_.name.empty()) | ||||||
|  |                { | ||||||
|  |                   markerRecords_.emplace_back( | ||||||
|  |                      std::make_shared<MarkerRecord>(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(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::shared_ptr<MarkerManager::Impl::MarkerRecord> | ||||||
|  | MarkerManager::Impl::GetMarkerByName(const std::string& name) | ||||||
|  | { | ||||||
|  |    for (auto& markerRecord : markerRecords_) | ||||||
|  |    { | ||||||
|  |       if (markerRecord->markerInfo_.name == name) | ||||||
|  |       { | ||||||
|  |          return markerRecord; | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return nullptr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MarkerManager::MarkerManager() : p(std::make_unique<Impl>(this)) | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |    boost::asio::post(p->threadPool_, | ||||||
|  |                      [this]() | ||||||
|  |                      { | ||||||
|  |                         try | ||||||
|  |                         { | ||||||
|  |                            p->InitializeMarkerSettings(); | ||||||
|  | 
 | ||||||
|  |                            // Read Marker settings on startup
 | ||||||
|  |                            main::Application::WaitForInitialization(); | ||||||
|  |                            p->ReadMarkerSettings(); | ||||||
|  | 
 | ||||||
|  |                            Q_EMIT MarkersInitialized(p->markerRecords_.size()); | ||||||
|  |                         } | ||||||
|  |                         catch (const std::exception& ex) | ||||||
|  |                         { | ||||||
|  |                            logger_->error(ex.what()); | ||||||
|  |                         } | ||||||
|  |                      }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MarkerManager::~MarkerManager() | ||||||
|  | { | ||||||
|  |    p->WriteMarkerSettings(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | size_t MarkerManager::marker_count() | ||||||
|  | { | ||||||
|  |    return p->markerRecords_.size(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::optional<types::MarkerInfo> MarkerManager::get_marker(size_t index) | ||||||
|  | { | ||||||
|  |    std::shared_lock lock(p->markerRecordLock_); | ||||||
|  |    if (index >= p->markerRecords_.size()) | ||||||
|  |    { | ||||||
|  |       return {}; | ||||||
|  |    } | ||||||
|  |    std::shared_ptr<MarkerManager::Impl::MarkerRecord>& markerRecord = | ||||||
|  |       p->markerRecords_[index]; | ||||||
|  |    return markerRecord->toMarkerInfo(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MarkerManager::set_marker(size_t index, const types::MarkerInfo& marker) | ||||||
|  | { | ||||||
|  |    { | ||||||
|  |       std::unique_lock lock(p->markerRecordLock_); | ||||||
|  |       if (index >= p->markerRecords_.size()) | ||||||
|  |       { | ||||||
|  |          return; | ||||||
|  |       } | ||||||
|  |       std::shared_ptr<MarkerManager::Impl::MarkerRecord>& markerRecord = | ||||||
|  |          p->markerRecords_[index]; | ||||||
|  |       markerRecord->markerInfo_ = marker; | ||||||
|  |    } | ||||||
|  |    Q_EMIT MarkerChanged(index); | ||||||
|  |    Q_EMIT MarkersUpdated(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MarkerManager::add_marker(const types::MarkerInfo& marker) | ||||||
|  | { | ||||||
|  |    { | ||||||
|  |       std::unique_lock lock(p->markerRecordLock_); | ||||||
|  |       p->markerRecords_.emplace_back(std::make_shared<Impl::MarkerRecord>(marker)); | ||||||
|  |    } | ||||||
|  |    Q_EMIT MarkerAdded(); | ||||||
|  |    Q_EMIT MarkersUpdated(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MarkerManager::remove_marker(size_t index) | ||||||
|  | { | ||||||
|  |    { | ||||||
|  |       std::unique_lock lock(p->markerRecordLock_); | ||||||
|  |       if (index >= p->markerRecords_.size()) | ||||||
|  |       { | ||||||
|  |          return; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       p->markerRecords_.erase(std::next(p->markerRecords_.begin(), index)); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    Q_EMIT MarkerRemoved(index); | ||||||
|  |    Q_EMIT MarkersUpdated(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MarkerManager::move_marker(size_t from, size_t to) | ||||||
|  | { | ||||||
|  |    { | ||||||
|  |       std::unique_lock lock(p->markerRecordLock_); | ||||||
|  |       if (from >= p->markerRecords_.size() || to >= p->markerRecords_.size()) | ||||||
|  |       { | ||||||
|  |          return; | ||||||
|  |       } | ||||||
|  |       std::shared_ptr<MarkerManager::Impl::MarkerRecord>& markerRecord = | ||||||
|  |          p->markerRecords_[from]; | ||||||
|  | 
 | ||||||
|  |       if (from == to) {} | ||||||
|  |       else if (from < to) | ||||||
|  |       { | ||||||
|  |          for (size_t i = from; i < to; i++) | ||||||
|  |          { | ||||||
|  |             p->markerRecords_[i] = p->markerRecords_[i + 1]; | ||||||
|  |          } | ||||||
|  |          p->markerRecords_[to] = markerRecord; | ||||||
|  |       } | ||||||
|  |       else | ||||||
|  |       { | ||||||
|  |          for (size_t i = from; i > to; i--) | ||||||
|  |          { | ||||||
|  |             p->markerRecords_[i] = p->markerRecords_[i - 1]; | ||||||
|  |          } | ||||||
|  |          p->markerRecords_[to] = markerRecord; | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  |    Q_EMIT MarkersUpdated(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | std::shared_ptr<MarkerManager> MarkerManager::Instance() | ||||||
|  | { | ||||||
|  |    static std::weak_ptr<MarkerManager> markerManagerReference_ {}; | ||||||
|  |    static std::mutex                   instanceMutex_ {}; | ||||||
|  | 
 | ||||||
|  |    std::unique_lock lock(instanceMutex_); | ||||||
|  | 
 | ||||||
|  |    std::shared_ptr<MarkerManager> markerManager = | ||||||
|  |       markerManagerReference_.lock(); | ||||||
|  | 
 | ||||||
|  |    if (markerManager == nullptr) | ||||||
|  |    { | ||||||
|  |       markerManager           = std::make_shared<MarkerManager>(); | ||||||
|  |       markerManagerReference_ = markerManager; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return markerManager; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace manager
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										46
									
								
								scwx-qt/source/scwx/qt/manager/marker_manager.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								scwx-qt/source/scwx/qt/manager/marker_manager.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/qt/types/marker_types.hpp> | ||||||
|  | 
 | ||||||
|  | #include <QObject> | ||||||
|  | #include <optional> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace manager | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class MarkerManager : public QObject | ||||||
|  | { | ||||||
|  |    Q_OBJECT | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |    explicit MarkerManager(); | ||||||
|  |    ~MarkerManager(); | ||||||
|  | 
 | ||||||
|  |    size_t                   marker_count(); | ||||||
|  |    std::optional<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<MarkerManager> Instance(); | ||||||
|  | 
 | ||||||
|  | signals: | ||||||
|  |    void MarkersInitialized(size_t count); | ||||||
|  |    void MarkersUpdated(); | ||||||
|  |    void MarkerChanged(size_t index); | ||||||
|  |    void MarkerAdded(); | ||||||
|  |    void MarkerRemoved(size_t index); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::unique_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace manager
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -12,6 +12,7 @@ | ||||||
| #include <scwx/qt/map/overlay_layer.hpp> | #include <scwx/qt/map/overlay_layer.hpp> | ||||||
| #include <scwx/qt/map/overlay_product_layer.hpp> | #include <scwx/qt/map/overlay_product_layer.hpp> | ||||||
| #include <scwx/qt/map/placefile_layer.hpp> | #include <scwx/qt/map/placefile_layer.hpp> | ||||||
|  | #include <scwx/qt/map/marker_layer.hpp> | ||||||
| #include <scwx/qt/map/radar_product_layer.hpp> | #include <scwx/qt/map/radar_product_layer.hpp> | ||||||
| #include <scwx/qt/map/radar_range_layer.hpp> | #include <scwx/qt/map/radar_range_layer.hpp> | ||||||
| #include <scwx/qt/map/radar_site_layer.hpp> | #include <scwx/qt/map/radar_site_layer.hpp> | ||||||
|  | @ -81,6 +82,7 @@ public: | ||||||
|        radarProductLayer_ {nullptr}, |        radarProductLayer_ {nullptr}, | ||||||
|        overlayLayer_ {nullptr}, |        overlayLayer_ {nullptr}, | ||||||
|        placefileLayer_ {nullptr}, |        placefileLayer_ {nullptr}, | ||||||
|  |        markerLayer_ {nullptr}, | ||||||
|        colorTableLayer_ {nullptr}, |        colorTableLayer_ {nullptr}, | ||||||
|        autoRefreshEnabled_ {true}, |        autoRefreshEnabled_ {true}, | ||||||
|        autoUpdateEnabled_ {true}, |        autoUpdateEnabled_ {true}, | ||||||
|  | @ -223,6 +225,7 @@ public: | ||||||
|    std::shared_ptr<OverlayLayer>        overlayLayer_; |    std::shared_ptr<OverlayLayer>        overlayLayer_; | ||||||
|    std::shared_ptr<OverlayProductLayer> overlayProductLayer_ {nullptr}; |    std::shared_ptr<OverlayProductLayer> overlayProductLayer_ {nullptr}; | ||||||
|    std::shared_ptr<PlacefileLayer>      placefileLayer_; |    std::shared_ptr<PlacefileLayer>      placefileLayer_; | ||||||
|  |    std::shared_ptr<MarkerLayer>            markerLayer_; | ||||||
|    std::shared_ptr<ColorTableLayer>     colorTableLayer_; |    std::shared_ptr<ColorTableLayer>     colorTableLayer_; | ||||||
|    std::shared_ptr<RadarSiteLayer>      radarSiteLayer_ {nullptr}; |    std::shared_ptr<RadarSiteLayer>      radarSiteLayer_ {nullptr}; | ||||||
| 
 | 
 | ||||||
|  | @ -1232,6 +1235,12 @@ void MapWidgetImpl::AddLayer(types::LayerType        type, | ||||||
|                  { widget_->RadarSiteRequested(id); }); |                  { widget_->RadarSiteRequested(id); }); | ||||||
|          break; |          break; | ||||||
| 
 | 
 | ||||||
|  |       // Create the location marker layer
 | ||||||
|  |       case types::InformationLayer::Markers: | ||||||
|  |          markerLayer_ = std::make_shared<MarkerLayer>(context_); | ||||||
|  |          AddLayer(layerName, markerLayer_, before); | ||||||
|  |          break; | ||||||
|  | 
 | ||||||
|       default: |       default: | ||||||
|          break; |          break; | ||||||
|       } |       } | ||||||
|  |  | ||||||
							
								
								
									
										113
									
								
								scwx-qt/source/scwx/qt/map/marker_layer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								scwx-qt/source/scwx/qt/map/marker_layer.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,113 @@ | ||||||
|  | #include <scwx/qt/map/marker_layer.hpp> | ||||||
|  | #include <scwx/qt/manager/marker_manager.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
|  | #include <scwx/qt/types/marker_types.hpp> | ||||||
|  | #include <scwx/qt/types/texture_types.hpp> | ||||||
|  | #include <scwx/qt/gl/draw/geo_icons.hpp> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | 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: | ||||||
|  |    explicit Impl(MarkerLayer* self, std::shared_ptr<MapContext> context) : | ||||||
|  |        self_ {self}, geoIcons_ {std::make_shared<gl::draw::GeoIcons>(context)} | ||||||
|  |    { | ||||||
|  |       ConnectSignals(); | ||||||
|  |    } | ||||||
|  |    ~Impl() {} | ||||||
|  | 
 | ||||||
|  |    void ReloadMarkers(); | ||||||
|  |    void ConnectSignals(); | ||||||
|  | 
 | ||||||
|  |    MarkerLayer* self_; | ||||||
|  |    const std::string& markerIconName_ { | ||||||
|  |       types::GetTextureName(types::ImageTexture::LocationMarker)}; | ||||||
|  | 
 | ||||||
|  |    std::shared_ptr<gl::draw::GeoIcons> 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++) | ||||||
|  |    { | ||||||
|  |       std::optional<types::MarkerInfo> marker = markerManager->get_marker(i); | ||||||
|  |       if (!marker) | ||||||
|  |       { | ||||||
|  |          break; | ||||||
|  |       } | ||||||
|  |       std::shared_ptr<gl::draw::GeoIconDrawItem> icon = geoIcons_->AddIcon(); | ||||||
|  |       geoIcons_->SetIconTexture(icon, markerIconName_, 0); | ||||||
|  |       geoIcons_->SetIconLocation(icon, marker->latitude, marker->longitude); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    geoIcons_->FinishIcons(); | ||||||
|  |    Q_EMIT self_->NeedsRendering(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MarkerLayer::MarkerLayer(const std::shared_ptr<MapContext>& context) : | ||||||
|  |     DrawLayer(context), p(std::make_unique<MarkerLayer::Impl>(this, context)) | ||||||
|  | { | ||||||
|  |    AddDrawItem(p->geoIcons_); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MarkerLayer::~MarkerLayer() = default; | ||||||
|  | 
 | ||||||
|  | void MarkerLayer::Initialize() | ||||||
|  | { | ||||||
|  |    logger_->debug("Initialize()"); | ||||||
|  |    DrawLayer::Initialize(); | ||||||
|  | 
 | ||||||
|  |    p->geoIcons_->StartIconSheets(); | ||||||
|  |    p->geoIcons_->AddIconSheet(p->markerIconName_); | ||||||
|  |    p->geoIcons_->FinishIconSheets(); | ||||||
|  | 
 | ||||||
|  |    p->ReloadMarkers(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MarkerLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) | ||||||
|  | { | ||||||
|  |    // auto markerManager = manager::MarkerManager::Instance();
 | ||||||
|  |    gl::OpenGLFunctions& gl = context()->gl(); | ||||||
|  | 
 | ||||||
|  |    DrawLayer::Render(params); | ||||||
|  | 
 | ||||||
|  |    SCWX_GL_CHECK_ERROR(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MarkerLayer::Deinitialize() | ||||||
|  | { | ||||||
|  |    logger_->debug("Deinitialize()"); | ||||||
|  | 
 | ||||||
|  |    DrawLayer::Deinitialize(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace map
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										33
									
								
								scwx-qt/source/scwx/qt/map/marker_layer.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								scwx-qt/source/scwx/qt/map/marker_layer.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <scwx/qt/map/draw_layer.hpp> | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace map | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class MarkerLayer : public DrawLayer | ||||||
|  | { | ||||||
|  |    Q_OBJECT | ||||||
|  | 
 | ||||||
|  | public: | ||||||
|  |    explicit MarkerLayer(const std::shared_ptr<MapContext>& context); | ||||||
|  |    ~MarkerLayer(); | ||||||
|  | 
 | ||||||
|  |    void Initialize() override final; | ||||||
|  |    void Render(const QMapLibre::CustomLayerRenderParameters&) override final; | ||||||
|  |    void Deinitialize() override final; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::unique_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace map
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -43,6 +43,7 @@ static const std::vector<types::LayerInfo> kDefaultLayers_ { | ||||||
|     types::InformationLayer::RadarSite, |     types::InformationLayer::RadarSite, | ||||||
|     false, |     false, | ||||||
|     {false, false, false, false}}, |     {false, false, false, false}}, | ||||||
|  |    {types::LayerType::Information, types::InformationLayer::Markers, true}, | ||||||
|    {types::LayerType::Data, types::DataLayer::RadarRange, true}, |    {types::LayerType::Data, types::DataLayer::RadarRange, true}, | ||||||
|    {types::LayerType::Alert, awips::Phenomenon::Tornado, true}, |    {types::LayerType::Alert, awips::Phenomenon::Tornado, true}, | ||||||
|    {types::LayerType::Alert, awips::Phenomenon::SnowSquall, true}, |    {types::LayerType::Alert, awips::Phenomenon::SnowSquall, true}, | ||||||
|  |  | ||||||
							
								
								
									
										290
									
								
								scwx-qt/source/scwx/qt/model/marker_model.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										290
									
								
								scwx-qt/source/scwx/qt/model/marker_model.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,290 @@ | ||||||
|  | #include <scwx/common/geographic.hpp> | ||||||
|  | #include <scwx/qt/model/marker_model.hpp> | ||||||
|  | #include <scwx/qt/manager/marker_manager.hpp> | ||||||
|  | #include <scwx/qt/types/marker_types.hpp> | ||||||
|  | #include <scwx/qt/types/qt_types.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
|  | 
 | ||||||
|  | #include <QApplication> | ||||||
|  | 
 | ||||||
|  | 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<int>(MarkerModel::Column::Latitude); | ||||||
|  | static constexpr int kLastColumn = | ||||||
|  |    static_cast<int>(MarkerModel::Column::Name); | ||||||
|  | static constexpr int kNumColumns = kLastColumn - kFirstColumn + 1; | ||||||
|  | 
 | ||||||
|  | class MarkerModel::Impl | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    explicit Impl() {} | ||||||
|  |    ~Impl() = default; | ||||||
|  |    std::shared_ptr<manager::MarkerManager> markerManager_ { | ||||||
|  |       manager::MarkerManager::Instance()}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | MarkerModel::MarkerModel(QObject* parent) : | ||||||
|  |    QAbstractTableModel(parent), p(std::make_unique<Impl>()) | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  |    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, | ||||||
|  |          &MarkerModel::HandleMarkerRemoved); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MarkerModel::~MarkerModel() = default; | ||||||
|  | 
 | ||||||
|  | int MarkerModel::rowCount(const QModelIndex& parent) const | ||||||
|  | { | ||||||
|  |    return parent.isValid() ? | ||||||
|  |              0 : | ||||||
|  |              static_cast<int>(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<int>(Column::Name): | ||||||
|  |    case static_cast<int>(Column::Latitude): | ||||||
|  |    case static_cast<int>(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 = 10; | ||||||
|  | 
 | ||||||
|  |    if (!index.isValid() || index.row() < 0) | ||||||
|  |    { | ||||||
|  |       return QVariant(); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    std::optional<types::MarkerInfo> markerInfo = | ||||||
|  |       p->markerManager_->get_marker(index.row()); | ||||||
|  |    if (!markerInfo) | ||||||
|  |    { | ||||||
|  |       return QVariant(); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    switch(index.column()) | ||||||
|  |    { | ||||||
|  |    case static_cast<int>(Column::Name): | ||||||
|  |       if (role == Qt::ItemDataRole::DisplayRole || | ||||||
|  |           role == Qt::ItemDataRole::ToolTipRole || | ||||||
|  |           role == Qt::ItemDataRole::EditRole) | ||||||
|  |       { | ||||||
|  |          return QString::fromStdString(markerInfo->name); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case static_cast<int>(Column::Latitude): | ||||||
|  |       if (role == Qt::ItemDataRole::DisplayRole || | ||||||
|  |           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); | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case static_cast<int>(Column::Longitude): | ||||||
|  |       if (role == Qt::ItemDataRole::DisplayRole || | ||||||
|  |           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; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    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<int>(Column::Name): | ||||||
|  |                return tr("Name"); | ||||||
|  | 
 | ||||||
|  |             case static_cast<int>(Column::Latitude): | ||||||
|  |                return tr("Latitude"); | ||||||
|  | 
 | ||||||
|  |             case static_cast<int>(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) | ||||||
|  |    { | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  |    std::optional<types::MarkerInfo> markerInfo = | ||||||
|  |       p->markerManager_->get_marker(index.row()); | ||||||
|  |    if (!markerInfo) | ||||||
|  |    { | ||||||
|  |       return false; | ||||||
|  |    } | ||||||
|  |    bool result = false; | ||||||
|  | 
 | ||||||
|  |    switch(index.column()) | ||||||
|  |    { | ||||||
|  |    case static_cast<int>(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<int>(Column::Latitude): | ||||||
|  |       if (role == Qt::ItemDataRole::EditRole) | ||||||
|  |       { | ||||||
|  |          QString str = value.toString(); | ||||||
|  |          bool ok; | ||||||
|  |          double latitude = str.toDouble(&ok); | ||||||
|  |          if (!str.isEmpty() && ok && -90 <= latitude && latitude <= 90) | ||||||
|  |          { | ||||||
|  |             markerInfo->latitude = latitude; | ||||||
|  |             p->markerManager_->set_marker(index.row(), *markerInfo); | ||||||
|  |             result = true; | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |       break; | ||||||
|  | 
 | ||||||
|  |    case static_cast<int>(Column::Longitude): | ||||||
|  |       if (role == Qt::ItemDataRole::EditRole) | ||||||
|  |       { | ||||||
|  |          QString str = value.toString(); | ||||||
|  |          bool ok; | ||||||
|  |          double longitude = str.toDouble(&ok); | ||||||
|  |          if (!str.isEmpty() && ok && -180 <= longitude && longitude <= 180) | ||||||
|  |          { | ||||||
|  |             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::HandleMarkersInitialized(size_t count) | ||||||
|  | { | ||||||
|  |    const int index = static_cast<int>(count - 1); | ||||||
|  | 
 | ||||||
|  |    beginInsertRows(QModelIndex(), 0, index); | ||||||
|  |    endInsertRows(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MarkerModel::HandleMarkerAdded() | ||||||
|  | { | ||||||
|  |    const int newIndex = static_cast<int>(p->markerManager_->marker_count() - 1); | ||||||
|  | 
 | ||||||
|  |    beginInsertRows(QModelIndex(), newIndex, newIndex); | ||||||
|  |    endInsertRows(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void MarkerModel::HandleMarkerChanged(size_t index) | ||||||
|  | { | ||||||
|  |    const int changedIndex = static_cast<int>(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<int>(index); | ||||||
|  | 
 | ||||||
|  |    beginRemoveRows(QModelIndex(), removedIndex, removedIndex); | ||||||
|  |    endRemoveRows(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace model
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										54
									
								
								scwx-qt/source/scwx/qt/model/marker_model.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								scwx-qt/source/scwx/qt/model/marker_model.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,54 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <QAbstractTableModel> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace model | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | class MarkerModel : public QAbstractTableModel | ||||||
|  | { | ||||||
|  | public: | ||||||
|  |    enum class Column : int | ||||||
|  |    { | ||||||
|  |       Latitude  = 0, | ||||||
|  |       Longitude = 1, | ||||||
|  |       Name      = 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 HandleMarkersInitialized(size_t count); | ||||||
|  |    void HandleMarkerAdded(); | ||||||
|  |    void HandleMarkerChanged(size_t index); | ||||||
|  |    void HandleMarkerRemoved(size_t index); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |    class Impl; | ||||||
|  |    std::unique_ptr<Impl> p; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace model
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
|  | @ -31,6 +31,7 @@ static const std::unordered_map<InformationLayer, std::string> | ||||||
|    informationLayerName_ {{InformationLayer::MapOverlay, "Map Overlay"}, |    informationLayerName_ {{InformationLayer::MapOverlay, "Map Overlay"}, | ||||||
|                           {InformationLayer::RadarSite, "Radar Sites"}, |                           {InformationLayer::RadarSite, "Radar Sites"}, | ||||||
|                           {InformationLayer::ColorTable, "Color Table"}, |                           {InformationLayer::ColorTable, "Color Table"}, | ||||||
|  |                           {InformationLayer::Markers, "Location Markers"}, | ||||||
|                           {InformationLayer::Unknown, "?"}}; |                           {InformationLayer::Unknown, "?"}}; | ||||||
| 
 | 
 | ||||||
| static const std::unordered_map<MapLayer, std::string> mapLayerName_ { | static const std::unordered_map<MapLayer, std::string> mapLayerName_ { | ||||||
|  |  | ||||||
|  | @ -44,6 +44,7 @@ enum class InformationLayer | ||||||
|    MapOverlay, |    MapOverlay, | ||||||
|    RadarSite, |    RadarSite, | ||||||
|    ColorTable, |    ColorTable, | ||||||
|  |    Markers, | ||||||
|    Unknown |    Unknown | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										26
									
								
								scwx-qt/source/scwx/qt/types/marker_types.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								scwx-qt/source/scwx/qt/types/marker_types.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | namespace scwx | ||||||
|  | { | ||||||
|  | namespace qt | ||||||
|  | { | ||||||
|  | namespace types | ||||||
|  | { | ||||||
|  | 
 | ||||||
|  | struct MarkerInfo | ||||||
|  | { | ||||||
|  |    MarkerInfo(const 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
 | ||||||
|  | @ -25,6 +25,8 @@ static const std::unordered_map<ImageTexture, TextureInfo> imageTextureInfo_ { | ||||||
|    {ImageTexture::Cursor17, |    {ImageTexture::Cursor17, | ||||||
|     {"images/cursor-17", ":/res/textures/images/cursor-17.png"}}, |     {"images/cursor-17", ":/res/textures/images/cursor-17.png"}}, | ||||||
|    {ImageTexture::Dot3, {"images/dot-3", ":/res/textures/images/dot-3.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, |    {ImageTexture::MapboxLogo, | ||||||
|     {"images/mapbox-logo", ":/res/textures/images/mapbox-logo.svg"}}, |     {"images/mapbox-logo", ":/res/textures/images/mapbox-logo.svg"}}, | ||||||
|    {ImageTexture::MapTilerLogo, |    {ImageTexture::MapTilerLogo, | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ enum class ImageTexture | ||||||
|    Crosshairs24, |    Crosshairs24, | ||||||
|    Cursor17, |    Cursor17, | ||||||
|    Dot3, |    Dot3, | ||||||
|  |    LocationMarker, | ||||||
|    MapboxLogo, |    MapboxLogo, | ||||||
|    MapTilerLogo |    MapTilerLogo | ||||||
| }; | }; | ||||||
|  |  | ||||||
							
								
								
									
										45
									
								
								scwx-qt/source/scwx/qt/ui/marker_dialog.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								scwx-qt/source/scwx/qt/ui/marker_dialog.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | ||||||
|  | #include "marker_dialog.hpp" | ||||||
|  | #include "ui_marker_dialog.h" | ||||||
|  | 
 | ||||||
|  | #include <scwx/qt/ui/marker_settings_widget.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
|  | 
 | ||||||
|  | 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<MarkerDialogImpl>()}, | ||||||
|  |     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
 | ||||||
							
								
								
									
										35
									
								
								scwx-qt/source/scwx/qt/ui/marker_dialog.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								scwx-qt/source/scwx/qt/ui/marker_dialog.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <QDialog> | ||||||
|  | 
 | ||||||
|  | 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<MarkerDialogImpl> p; | ||||||
|  |    Ui::MarkerDialog*                 ui; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace ui
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										88
									
								
								scwx-qt/source/scwx/qt/ui/marker_dialog.ui
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								scwx-qt/source/scwx/qt/ui/marker_dialog.ui
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,88 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <ui version="4.0"> | ||||||
|  |  <class>MarkerDialog</class> | ||||||
|  |  <widget class="QDialog" name="MarkerDialog"> | ||||||
|  |   <property name="geometry"> | ||||||
|  |    <rect> | ||||||
|  |     <x>0</x> | ||||||
|  |     <y>0</y> | ||||||
|  |     <width>700</width> | ||||||
|  |     <height>600</height> | ||||||
|  |    </rect> | ||||||
|  |   </property> | ||||||
|  |   <property name="windowTitle"> | ||||||
|  |    <string>Marker Manager</string> | ||||||
|  |   </property> | ||||||
|  |   <layout class="QVBoxLayout" name="verticalLayout"> | ||||||
|  |    <item> | ||||||
|  |     <widget class="QFrame" name="contentsFrame"> | ||||||
|  |      <property name="frameShape"> | ||||||
|  |       <enum>QFrame::StyledPanel</enum> | ||||||
|  |      </property> | ||||||
|  |      <property name="frameShadow"> | ||||||
|  |       <enum>QFrame::Raised</enum> | ||||||
|  |      </property> | ||||||
|  |      <layout class="QVBoxLayout" name="verticalLayout_2"> | ||||||
|  |       <property name="leftMargin"> | ||||||
|  |        <number>0</number> | ||||||
|  |       </property> | ||||||
|  |       <property name="topMargin"> | ||||||
|  |        <number>0</number> | ||||||
|  |       </property> | ||||||
|  |       <property name="rightMargin"> | ||||||
|  |        <number>0</number> | ||||||
|  |       </property> | ||||||
|  |       <property name="bottomMargin"> | ||||||
|  |        <number>0</number> | ||||||
|  |       </property> | ||||||
|  |      </layout> | ||||||
|  |     </widget> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <widget class="QDialogButtonBox" name="buttonBox"> | ||||||
|  |      <property name="orientation"> | ||||||
|  |       <enum>Qt::Horizontal</enum> | ||||||
|  |      </property> | ||||||
|  |      <property name="standardButtons"> | ||||||
|  |       <set>QDialogButtonBox::Close</set> | ||||||
|  |      </property> | ||||||
|  |     </widget> | ||||||
|  |    </item> | ||||||
|  |   </layout> | ||||||
|  |  </widget> | ||||||
|  |  <resources/> | ||||||
|  |  <connections> | ||||||
|  |   <connection> | ||||||
|  |    <sender>buttonBox</sender> | ||||||
|  |    <signal>accepted()</signal> | ||||||
|  |    <receiver>MarkerDialog</receiver> | ||||||
|  |    <slot>accept()</slot> | ||||||
|  |    <hints> | ||||||
|  |     <hint type="sourcelabel"> | ||||||
|  |      <x>248</x> | ||||||
|  |      <y>254</y> | ||||||
|  |     </hint> | ||||||
|  |     <hint type="destinationlabel"> | ||||||
|  |      <x>157</x> | ||||||
|  |      <y>274</y> | ||||||
|  |     </hint> | ||||||
|  |    </hints> | ||||||
|  |   </connection> | ||||||
|  |   <connection> | ||||||
|  |    <sender>buttonBox</sender> | ||||||
|  |    <signal>rejected()</signal> | ||||||
|  |    <receiver>MarkerDialog</receiver> | ||||||
|  |    <slot>reject()</slot> | ||||||
|  |    <hints> | ||||||
|  |     <hint type="sourcelabel"> | ||||||
|  |      <x>316</x> | ||||||
|  |      <y>260</y> | ||||||
|  |     </hint> | ||||||
|  |     <hint type="destinationlabel"> | ||||||
|  |      <x>286</x> | ||||||
|  |      <y>274</y> | ||||||
|  |     </hint> | ||||||
|  |    </hints> | ||||||
|  |   </connection> | ||||||
|  |  </connections> | ||||||
|  | </ui> | ||||||
							
								
								
									
										105
									
								
								scwx-qt/source/scwx/qt/ui/marker_settings_widget.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								scwx-qt/source/scwx/qt/ui/marker_settings_widget.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,105 @@ | ||||||
|  | #include "marker_settings_widget.hpp" | ||||||
|  | #include "ui_marker_settings_widget.h" | ||||||
|  | 
 | ||||||
|  | #include <scwx/qt/manager/marker_manager.hpp> | ||||||
|  | #include <scwx/qt/model/marker_model.hpp> | ||||||
|  | #include <scwx/qt/types/qt_types.hpp> | ||||||
|  | #include <scwx/qt/ui/open_url_dialog.hpp> | ||||||
|  | #include <scwx/util/logger.hpp> | ||||||
|  | 
 | ||||||
|  | #include <QSortFilterProxyModel> | ||||||
|  | 
 | ||||||
|  | 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<manager::MarkerManager> markerManager_ { | ||||||
|  |       manager::MarkerManager::Instance()}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | MarkerSettingsWidget::MarkerSettingsWidget(QWidget* parent) : | ||||||
|  |     QFrame(parent), | ||||||
|  |     p {std::make_unique<MarkerSettingsWidgetImpl>(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<int>( | ||||||
|  |                                 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
 | ||||||
							
								
								
									
										35
									
								
								scwx-qt/source/scwx/qt/ui/marker_settings_widget.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								scwx-qt/source/scwx/qt/ui/marker_settings_widget.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <QFrame> | ||||||
|  | 
 | ||||||
|  | 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<MarkerSettingsWidgetImpl> p; | ||||||
|  |    Ui::MarkerSettingsWidget*                 ui; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace ui
 | ||||||
|  | } // namespace qt
 | ||||||
|  | } // namespace scwx
 | ||||||
							
								
								
									
										88
									
								
								scwx-qt/source/scwx/qt/ui/marker_settings_widget.ui
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								scwx-qt/source/scwx/qt/ui/marker_settings_widget.ui
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,88 @@ | ||||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||||
|  | <ui version="4.0"> | ||||||
|  |  <class>MarkerSettingsWidget</class> | ||||||
|  |  <widget class="QFrame" name="MarkerSettingsWidget"> | ||||||
|  |   <property name="geometry"> | ||||||
|  |    <rect> | ||||||
|  |     <x>0</x> | ||||||
|  |     <y>0</y> | ||||||
|  |     <width>400</width> | ||||||
|  |     <height>300</height> | ||||||
|  |    </rect> | ||||||
|  |   </property> | ||||||
|  |   <property name="windowTitle"> | ||||||
|  |    <string>Frame</string> | ||||||
|  |   </property> | ||||||
|  |   <layout class="QVBoxLayout" name="verticalLayout"> | ||||||
|  |    <item> | ||||||
|  |     <widget class="QTreeView" name="markerView"> | ||||||
|  |      <property name="alternatingRowColors"> | ||||||
|  |       <bool>true</bool> | ||||||
|  |      </property> | ||||||
|  |      <property name="indentation"> | ||||||
|  |       <number>0</number> | ||||||
|  |      </property> | ||||||
|  |      <property name="sortingEnabled"> | ||||||
|  |       <bool>true</bool> | ||||||
|  |      </property> | ||||||
|  |     </widget> | ||||||
|  |    </item> | ||||||
|  |    <item> | ||||||
|  |     <widget class="QFrame" name="buttonFrame"> | ||||||
|  |      <property name="frameShape"> | ||||||
|  |       <enum>QFrame::Shape::StyledPanel</enum> | ||||||
|  |      </property> | ||||||
|  |      <property name="frameShadow"> | ||||||
|  |       <enum>QFrame::Shadow::Raised</enum> | ||||||
|  |      </property> | ||||||
|  |      <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||||||
|  |       <property name="leftMargin"> | ||||||
|  |        <number>0</number> | ||||||
|  |       </property> | ||||||
|  |       <property name="topMargin"> | ||||||
|  |        <number>0</number> | ||||||
|  |       </property> | ||||||
|  |       <property name="rightMargin"> | ||||||
|  |        <number>0</number> | ||||||
|  |       </property> | ||||||
|  |       <property name="bottomMargin"> | ||||||
|  |        <number>0</number> | ||||||
|  |       </property> | ||||||
|  |       <item> | ||||||
|  |        <spacer name="horizontalSpacer"> | ||||||
|  |         <property name="orientation"> | ||||||
|  |          <enum>Qt::Orientation::Horizontal</enum> | ||||||
|  |         </property> | ||||||
|  |         <property name="sizeHint" stdset="0"> | ||||||
|  |          <size> | ||||||
|  |           <width>40</width> | ||||||
|  |           <height>20</height> | ||||||
|  |          </size> | ||||||
|  |         </property> | ||||||
|  |        </spacer> | ||||||
|  |       </item> | ||||||
|  |       <item> | ||||||
|  |        <widget class="QPushButton" name="addButton"> | ||||||
|  |         <property name="text"> | ||||||
|  |          <string>&Add</string> | ||||||
|  |         </property> | ||||||
|  |        </widget> | ||||||
|  |       </item> | ||||||
|  |       <item> | ||||||
|  |        <widget class="QPushButton" name="removeButton"> | ||||||
|  |         <property name="enabled"> | ||||||
|  |          <bool>false</bool> | ||||||
|  |         </property> | ||||||
|  |         <property name="text"> | ||||||
|  |          <string>R&emove</string> | ||||||
|  |         </property> | ||||||
|  |        </widget> | ||||||
|  |       </item> | ||||||
|  |      </layout> | ||||||
|  |     </widget> | ||||||
|  |    </item> | ||||||
|  |   </layout> | ||||||
|  |  </widget> | ||||||
|  |  <resources/> | ||||||
|  |  <connections/> | ||||||
|  | </ui> | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat