mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-30 23:30:04 +00:00 
			
		
		
		
	Add custom marker icons, and rework how marker icons are handled.
This commit is contained in:
		
							parent
							
								
									3685599693
								
							
						
					
					
						commit
						5bb4a7f95a
					
				
					 10 changed files with 368 additions and 204 deletions
				
			
		|  | @ -239,7 +239,6 @@ set(SRC_TYPES source/scwx/qt/types/alert_types.cpp | |||
|               source/scwx/qt/types/layer_types.cpp | ||||
|               source/scwx/qt/types/location_types.cpp | ||||
|               source/scwx/qt/types/map_types.cpp | ||||
|               source/scwx/qt/types/marker_types.cpp | ||||
|               source/scwx/qt/types/media_types.cpp | ||||
|               source/scwx/qt/types/qt_types.cpp | ||||
|               source/scwx/qt/types/radar_product_record.cpp | ||||
|  |  | |||
|  | @ -2,13 +2,16 @@ | |||
| #include <scwx/qt/types/marker_types.hpp> | ||||
| #include <scwx/qt/util/color.hpp> | ||||
| #include <scwx/qt/util/json.hpp> | ||||
| #include <scwx/qt/util/texture_atlas.hpp> | ||||
| #include <scwx/qt/main/application.hpp> | ||||
| #include <scwx/qt/manager/resource_manager.hpp> | ||||
| #include <scwx/util/logger.hpp> | ||||
| 
 | ||||
| #include <filesystem> | ||||
| #include <shared_mutex> | ||||
| #include <vector> | ||||
| #include <string> | ||||
| #include <unordered_map> | ||||
| 
 | ||||
| #include <QStandardPaths> | ||||
| #include <boost/json.hpp> | ||||
|  | @ -25,12 +28,13 @@ 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"; | ||||
| static const std::string kIconName_      = "icon"; | ||||
| static const std::string kIconColorName_ = "icon-color"; | ||||
| static const std::string kNameName_       = "name"; | ||||
| static const std::string kLatitudeName_   = "latitude"; | ||||
| static const std::string kLongitudeName_  = "longitude"; | ||||
| static const std::string kIconName_       = "icon"; | ||||
| static const std::string kIconColorName_  = "icon-color"; | ||||
| 
 | ||||
| static const std::string defaultIconName = "images/location-marker"; | ||||
| 
 | ||||
| class MarkerManager::Impl | ||||
| { | ||||
|  | @ -40,15 +44,16 @@ public: | |||
|    explicit Impl(MarkerManager* self) : self_ {self} {} | ||||
|    ~Impl() { threadPool_.join(); } | ||||
| 
 | ||||
|    std::string                                markerSettingsPath_ {""}; | ||||
|    std::vector<std::shared_ptr<MarkerRecord>> markerRecords_ {}; | ||||
|    std::string                                 markerSettingsPath_ {""}; | ||||
|    std::vector<std::shared_ptr<MarkerRecord>>  markerRecords_ {}; | ||||
|    std::unordered_map<types::MarkerId, size_t> idToIndex_ {}; | ||||
| 
 | ||||
|    std::unordered_map<std::string, types::MarkerIconInfo> markerIcons_ {}; | ||||
| 
 | ||||
|    MarkerManager* self_; | ||||
| 
 | ||||
|    boost::asio::thread_pool threadPool_ {1u}; | ||||
|    std::shared_mutex        markerRecordLock_ {}; | ||||
|    std::shared_mutex        markerIconsLock_ {}; | ||||
| 
 | ||||
|    void                          InitializeMarkerSettings(); | ||||
|    void                          ReadMarkerSettings(); | ||||
|  | @ -57,7 +62,7 @@ public: | |||
| 
 | ||||
|    void InitalizeIds(); | ||||
|    types::MarkerId NewId(); | ||||
|    types::MarkerId lastId_; | ||||
|    types::MarkerId lastId_ {0}; | ||||
| }; | ||||
| 
 | ||||
| class MarkerManager::Impl::MarkerRecord | ||||
|  | @ -84,14 +89,14 @@ public: | |||
|             {kLatitudeName_, record->markerInfo_.latitude}, | ||||
|             {kLongitudeName_, record->markerInfo_.longitude}, | ||||
|             {kIconName_, record->markerInfo_.iconName}, | ||||
|             {kIconColorName_, util::color::ToArgbString(record->markerInfo_.iconColor)}}; | ||||
|             {kIconColorName_, | ||||
|              util::color::ToArgbString(record->markerInfo_.iconColor)}}; | ||||
|    } | ||||
| 
 | ||||
| 
 | ||||
|    friend MarkerRecord tag_invoke(boost::json::value_to_tag<MarkerRecord>, | ||||
|                                   const boost::json::value& jv) | ||||
|    { | ||||
|       static const std::string defaultIconName = types::getMarkerIcons()[0].name; | ||||
|       static const boost::gil::rgba8_pixel_t defaultIconColor = | ||||
|          util::color::ToRgba8PixelT("#ffff0000"); | ||||
| 
 | ||||
|  | @ -120,12 +125,12 @@ public: | |||
|          } | ||||
|       } | ||||
| 
 | ||||
|       return MarkerRecord(types::MarkerInfo( | ||||
|       return {types::MarkerInfo( | ||||
|          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_)), | ||||
|          iconName, | ||||
|          iconColor)); | ||||
|          iconColor)}; | ||||
|    } | ||||
| }; | ||||
| 
 | ||||
|  | @ -176,14 +181,14 @@ void MarkerManager::Impl::ReadMarkerSettings() | |||
|       { | ||||
|          // For each marker entry
 | ||||
|          auto& markerArray = markerJson.as_array(); | ||||
|          //std::vector<std::string> fileNames {};
 | ||||
|          markerRecords_.reserve(markerArray.size()); | ||||
|          idToIndex_.reserve(markerArray.size()); | ||||
|          for (auto& markerEntry : markerArray) | ||||
|          { | ||||
|             try | ||||
|             { | ||||
|                MarkerRecord record = | ||||
|                   boost::json::value_to<MarkerRecord>(markerEntry); | ||||
|                auto record = boost::json::value_to<MarkerRecord>(markerEntry); | ||||
| 
 | ||||
|                if (!record.markerInfo_.name.empty()) | ||||
|                { | ||||
|  | @ -193,6 +198,8 @@ void MarkerManager::Impl::ReadMarkerSettings() | |||
|                   markerRecords_.emplace_back( | ||||
|                      std::make_shared<MarkerRecord>(record.markerInfo_)); | ||||
|                   idToIndex_.emplace(id, index); | ||||
| 
 | ||||
|                   self_->add_icon(record.markerInfo_.iconName, true); | ||||
|                } | ||||
|             } | ||||
|             catch (const std::exception& ex) | ||||
|  | @ -201,10 +208,14 @@ void MarkerManager::Impl::ReadMarkerSettings() | |||
|             } | ||||
|          } | ||||
| 
 | ||||
|          util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); | ||||
|          textureAtlas.BuildAtlas(2048, 2048); // TODO should code be moved to ResourceManager (probrably)
 | ||||
| 
 | ||||
|          logger_->debug("{} location marker entries", markerRecords_.size()); | ||||
|       } | ||||
|    } | ||||
| 
 | ||||
| 
 | ||||
|    Q_EMIT self_->MarkersUpdated(); | ||||
| } | ||||
| 
 | ||||
|  | @ -233,17 +244,41 @@ MarkerManager::Impl::GetMarkerByName(const std::string& name) | |||
| 
 | ||||
| MarkerManager::MarkerManager() : p(std::make_unique<Impl>(this)) | ||||
| { | ||||
|    const std::vector<types::MarkerIconInfo> defaultMarkerIcons_ { | ||||
|       types::MarkerIconInfo(types::ImageTexture::LocationMarker, -1, -1), | ||||
|       types::MarkerIconInfo(types::ImageTexture::LocationPin, 6, 16), | ||||
|       types::MarkerIconInfo(types::ImageTexture::LocationCrosshair, -1, -1), | ||||
|       types::MarkerIconInfo(types::ImageTexture::LocationStar, -1, -1), | ||||
|       types::MarkerIconInfo(types::ImageTexture::LocationBriefcase, -1, -1), | ||||
|       types::MarkerIconInfo( | ||||
|          types::ImageTexture::LocationBuildingColumns, -1, -1), | ||||
|       types::MarkerIconInfo(types::ImageTexture::LocationBuilding, -1, -1), | ||||
|       types::MarkerIconInfo(types::ImageTexture::LocationCaravan, -1, -1), | ||||
|       types::MarkerIconInfo(types::ImageTexture::LocationHouse, -1, -1), | ||||
|       types::MarkerIconInfo(types::ImageTexture::LocationTent, -1, -1), | ||||
|    }; | ||||
| 
 | ||||
|    p->InitializeMarkerSettings(); | ||||
| 
 | ||||
|    boost::asio::post(p->threadPool_, | ||||
|                      [this]() | ||||
|                      [this, defaultMarkerIcons_]() | ||||
|                      { | ||||
|                         try | ||||
|                         { | ||||
|                            // Read Marker settings on startup
 | ||||
|                            main::Application::WaitForInitialization(); | ||||
|                            { | ||||
|                               std::unique_lock lock(p->markerIconsLock_); | ||||
|                               p->markerIcons_.reserve( | ||||
|                                  defaultMarkerIcons_.size()); | ||||
|                               for (auto& icon : defaultMarkerIcons_) | ||||
|                               { | ||||
|                                  p->markerIcons_.emplace(icon.name, icon); | ||||
|                               } | ||||
|                            } | ||||
|                            p->ReadMarkerSettings(); | ||||
| 
 | ||||
|                            Q_EMIT IconsReady(); | ||||
|                            Q_EMIT MarkersInitialized(p->markerRecords_.size()); | ||||
|                         } | ||||
|                         catch (const std::exception& ex) | ||||
|  | @ -310,6 +345,8 @@ void MarkerManager::set_marker(types::MarkerId          id, | |||
|          p->markerRecords_[index]; | ||||
|       markerRecord->markerInfo_ = marker; | ||||
|       markerRecord->markerInfo_.id = id; | ||||
| 
 | ||||
|       add_icon(marker.iconName); | ||||
|    } | ||||
|    Q_EMIT MarkerChanged(id); | ||||
|    Q_EMIT MarkersUpdated(); | ||||
|  | @ -325,6 +362,8 @@ types::MarkerId MarkerManager::add_marker(const types::MarkerInfo& marker) | |||
|       p->idToIndex_.emplace(id, index); | ||||
|       p->markerRecords_.emplace_back(std::make_shared<Impl::MarkerRecord>(marker)); | ||||
|       p->markerRecords_[index]->markerInfo_.id = id; | ||||
| 
 | ||||
|       add_icon(marker.iconName); | ||||
|    } | ||||
|    Q_EMIT MarkerAdded(id); | ||||
|    Q_EMIT MarkersUpdated(); | ||||
|  | @ -403,6 +442,48 @@ void MarkerManager::for_each(std::function<MarkerForEachFunc> func) | |||
|    } | ||||
| } | ||||
| 
 | ||||
| void MarkerManager::add_icon(const std::string& name, bool startup) | ||||
| { | ||||
|    { | ||||
|       std::unique_lock lock(p->markerIconsLock_); | ||||
|       if (p->markerIcons_.contains(name)) | ||||
|       { | ||||
|          return; | ||||
|       } | ||||
|       std::shared_ptr<boost::gil::rgba8_image_t> image = | ||||
|          ResourceManager::LoadImageResource(name); | ||||
| 
 | ||||
|       auto icon = types::MarkerIconInfo(name, -1, -1, image); | ||||
|       p->markerIcons_.emplace(name, icon); | ||||
|    } | ||||
| 
 | ||||
|    if (!startup) | ||||
|    { | ||||
|       util::TextureAtlas& textureAtlas = util::TextureAtlas::Instance(); | ||||
|       textureAtlas.BuildAtlas(2048, 2048); // TODO should code be moved to ResourceManager (probrably)
 | ||||
|       Q_EMIT IconAdded(name); | ||||
|    } | ||||
| } | ||||
| 
 | ||||
| std::optional<types::MarkerIconInfo> | ||||
| MarkerManager::get_icon(const std::string& name) | ||||
| { | ||||
|    std::shared_lock lock(p->markerIconsLock_); | ||||
|    if (p->markerIcons_.contains(name)) | ||||
|    { | ||||
|       return p->markerIcons_.at(name); | ||||
|    } | ||||
| 
 | ||||
|    return {}; | ||||
| } | ||||
| 
 | ||||
| const std::unordered_map<std::string, types::MarkerIconInfo> | ||||
| MarkerManager::get_icons() | ||||
| { | ||||
|    std::shared_lock lock(p->markerIconsLock_); | ||||
|    return p->markerIcons_; | ||||
| } | ||||
| 
 | ||||
| // Only use for testing
 | ||||
| void MarkerManager::set_marker_settings_path(const std::string& path) | ||||
| { | ||||
|  | @ -429,6 +510,11 @@ std::shared_ptr<MarkerManager> MarkerManager::Instance() | |||
|    return markerManager; | ||||
| } | ||||
| 
 | ||||
| const std::string& MarkerManager::getDefaultIconName() | ||||
| { | ||||
|    return defaultIconName; | ||||
| } | ||||
| 
 | ||||
| } // namespace manager
 | ||||
| } // namespace qt
 | ||||
| } // namespace scwx
 | ||||
|  |  | |||
|  | @ -29,12 +29,17 @@ public: | |||
|    void remove_marker(types::MarkerId id); | ||||
|    void move_marker(size_t from, size_t to); | ||||
| 
 | ||||
|    void add_icon(const std::string& name, bool startup = false); | ||||
|    std::optional<types::MarkerIconInfo> get_icon(const std::string& name); | ||||
|    const std::unordered_map<std::string, types::MarkerIconInfo> get_icons(); | ||||
| 
 | ||||
|    void for_each(std::function<MarkerForEachFunc> func); | ||||
| 
 | ||||
|    // Only use for testing
 | ||||
|    void set_marker_settings_path(const std::string& path); | ||||
| 
 | ||||
|    static std::shared_ptr<MarkerManager> Instance(); | ||||
|    static const std::string& getDefaultIconName(); | ||||
| 
 | ||||
| signals: | ||||
|    void MarkersInitialized(size_t count); | ||||
|  | @ -43,6 +48,10 @@ signals: | |||
|    void MarkerAdded(types::MarkerId id); | ||||
|    void MarkerRemoved(types::MarkerId id); | ||||
| 
 | ||||
|    void IconsReady(); | ||||
|    void IconAdded(std::string name); | ||||
| 
 | ||||
| 
 | ||||
| private: | ||||
|    class Impl; | ||||
|    std::unique_ptr<Impl> p; | ||||
|  |  | |||
|  | @ -30,11 +30,16 @@ public: | |||
|    { | ||||
|       ConnectSignals(); | ||||
|    } | ||||
|    ~Impl() {} | ||||
|    ~Impl() = default; | ||||
| 
 | ||||
|    void ReloadMarkers(); | ||||
|    void ConnectSignals(); | ||||
| 
 | ||||
|    std::shared_ptr<manager::MarkerManager> markerManager_ { | ||||
|       manager::MarkerManager::Instance()}; | ||||
| 
 | ||||
|    void set_icon_sheets(); | ||||
| 
 | ||||
|    MarkerLayer* self_; | ||||
| 
 | ||||
|    std::shared_ptr<gl::draw::GeoIcons> geoIcons_; | ||||
|  | @ -43,25 +48,26 @@ public: | |||
| 
 | ||||
| void MarkerLayer::Impl::ConnectSignals() | ||||
| { | ||||
|    auto markerManager = manager::MarkerManager::Instance(); | ||||
| 
 | ||||
|    QObject::connect(markerManager.get(), | ||||
|          &manager::MarkerManager::MarkersUpdated, | ||||
|          self_, | ||||
|          [this]() | ||||
|          { | ||||
|             this->ReloadMarkers(); | ||||
|          }); | ||||
|    QObject::connect(markerManager_.get(), | ||||
|                     &manager::MarkerManager::MarkersUpdated, | ||||
|                     self_, | ||||
|                     [this]() { ReloadMarkers(); }); | ||||
|    QObject::connect(markerManager_.get(), | ||||
|                     &manager::MarkerManager::IconsReady, | ||||
|                     self_, | ||||
|                     [this]() { set_icon_sheets(); }); | ||||
|    QObject::connect(markerManager_.get(), | ||||
|                     &manager::MarkerManager::IconAdded, | ||||
|                     self_, | ||||
|                     [this]() { set_icon_sheets(); }); | ||||
| } | ||||
| 
 | ||||
| void MarkerLayer::Impl::ReloadMarkers() | ||||
| { | ||||
|    logger_->debug("ReloadMarkers()"); | ||||
|    auto markerManager = manager::MarkerManager::Instance(); | ||||
| 
 | ||||
|    geoIcons_->StartIcons(); | ||||
| 
 | ||||
|    markerManager->for_each( | ||||
|    markerManager_->for_each( | ||||
|       [this](const types::MarkerInfo& marker) | ||||
|       { | ||||
|          // must use local ID, instead of reference to marker in event handler
 | ||||
|  | @ -69,6 +75,7 @@ void MarkerLayer::Impl::ReloadMarkers() | |||
|          types::MarkerId id = marker.id; | ||||
| 
 | ||||
|          std::shared_ptr<gl::draw::GeoIconDrawItem> icon = geoIcons_->AddIcon(); | ||||
| 
 | ||||
|          geoIcons_->SetIconTexture(icon, marker.iconName, 0); | ||||
|          geoIcons_->SetIconLocation(icon, marker.latitude, marker.longitude); | ||||
|          geoIcons_->SetIconHoverText(icon, marker.name); | ||||
|  | @ -81,7 +88,7 @@ void MarkerLayer::Impl::ReloadMarkers() | |||
|                { | ||||
|                case QEvent::Type::MouseButtonPress: | ||||
|                { | ||||
|                   QMouseEvent* mouseEvent = reinterpret_cast<QMouseEvent*>(ev); | ||||
|                   auto* mouseEvent = reinterpret_cast<QMouseEvent*>(ev); | ||||
|                   if (mouseEvent->buttons() == Qt::MouseButton::RightButton) | ||||
|                   { | ||||
|                      editMarkerDialog_->setup(id); | ||||
|  | @ -113,17 +120,24 @@ void MarkerLayer::Initialize() | |||
|    logger_->debug("Initialize()"); | ||||
|    DrawLayer::Initialize(); | ||||
| 
 | ||||
|    p->geoIcons_->StartIconSheets(); | ||||
|    for (auto& markerIcon : types::getMarkerIcons()) | ||||
|    { | ||||
|       p->geoIcons_->AddIconSheet( | ||||
|          markerIcon.name, 0, 0, markerIcon.hotX, markerIcon.hotY); | ||||
|    } | ||||
|    p->geoIcons_->FinishIconSheets(); | ||||
| 
 | ||||
|    p->set_icon_sheets(); | ||||
|    p->ReloadMarkers(); | ||||
| } | ||||
| 
 | ||||
| void MarkerLayer::Impl::set_icon_sheets() | ||||
| { | ||||
|    geoIcons_->StartIconSheets(); | ||||
|    for (auto& markerIcon : markerManager_->get_icons()) | ||||
|    { | ||||
|       geoIcons_->AddIconSheet(markerIcon.second.name, | ||||
|                               0, | ||||
|                               0, | ||||
|                               markerIcon.second.hotX, | ||||
|                               markerIcon.second.hotY); | ||||
|    } | ||||
|    geoIcons_->FinishIconSheets(); | ||||
| } | ||||
| 
 | ||||
| void MarkerLayer::Render(const QMapLibre::CustomLayerRenderParameters& params) | ||||
| { | ||||
|    gl::OpenGLFunctions& gl = context()->gl(); | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ namespace model | |||
| 
 | ||||
| static const std::string logPrefix_ = "scwx::qt::model::marker_model"; | ||||
| static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||
| static const int         iconSize_  = 30; | ||||
| 
 | ||||
| static constexpr int kFirstColumn = | ||||
|    static_cast<int>(MarkerModel::Column::Latitude); | ||||
|  | @ -130,17 +131,19 @@ QVariant MarkerModel::data(const QModelIndex& index, int role) const | |||
|    case static_cast<int>(Column::Icon): | ||||
|       if (role == Qt::ItemDataRole::DecorationRole) | ||||
|       { | ||||
|          for (auto& icon : types::getMarkerIcons()) | ||||
|          std::optional<types::MarkerIconInfo> icon = | ||||
|             p->markerManager_->get_icon(markerInfo->iconName); | ||||
|          if (icon) { | ||||
|             return util::modulateColors(icon->qIcon, | ||||
|                                         QSize(iconSize_, iconSize_), | ||||
|                                         QColor(markerInfo->iconColor[0], | ||||
|                                                markerInfo->iconColor[1], | ||||
|                                                markerInfo->iconColor[2], | ||||
|                                                markerInfo->iconColor[3])); | ||||
|          } | ||||
|          else | ||||
|          { | ||||
|             if (icon.name == markerInfo->iconName) | ||||
|             { | ||||
|                return util::modulateColors(icon.qIcon, | ||||
|                                            QSize(30, 30), | ||||
|                                            QColor(markerInfo->iconColor[0], | ||||
|                                                   markerInfo->iconColor[1], | ||||
|                                                   markerInfo->iconColor[2], | ||||
|                                                   markerInfo->iconColor[3])); | ||||
|             } | ||||
|             return {}; | ||||
|          } | ||||
|       } | ||||
|       break; | ||||
|  |  | |||
|  | @ -1,34 +0,0 @@ | |||
| #include <scwx/qt/types/marker_types.hpp> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
| namespace qt | ||||
| { | ||||
| namespace types | ||||
| { | ||||
| 
 | ||||
| const std::vector<MarkerIconInfo>& getMarkerIcons() | ||||
| { | ||||
|    static std::vector<MarkerIconInfo> markerIcons = {}; | ||||
|    if (markerIcons.size() == 0) | ||||
|    { | ||||
|       markerIcons = { | ||||
|          MarkerIconInfo(types::ImageTexture::LocationMarker, -1, -1), | ||||
|          MarkerIconInfo(types::ImageTexture::LocationPin, 6, 16), | ||||
|          MarkerIconInfo(types::ImageTexture::LocationCrosshair, -1, -1), | ||||
|          MarkerIconInfo(types::ImageTexture::LocationStar, -1, -1), | ||||
|          MarkerIconInfo(types::ImageTexture::LocationBriefcase, -1, -1), | ||||
|          MarkerIconInfo(types::ImageTexture::LocationBuildingColumns, -1, -1), | ||||
|          MarkerIconInfo(types::ImageTexture::LocationBuilding, -1, -1), | ||||
|          MarkerIconInfo(types::ImageTexture::LocationCaravan, -1, -1), | ||||
|          MarkerIconInfo(types::ImageTexture::LocationHouse, -1, -1), | ||||
|          MarkerIconInfo(types::ImageTexture::LocationTent, -1, -1), | ||||
|       }; | ||||
|    } | ||||
| 
 | ||||
|    return markerIcons; | ||||
| } | ||||
| 
 | ||||
| } // namespace types
 | ||||
| } // namespace qt
 | ||||
| } // namespace scwx
 | ||||
|  | @ -14,15 +14,15 @@ namespace qt | |||
| { | ||||
| namespace types | ||||
| { | ||||
| typedef std::uint64_t MarkerId; | ||||
| using MarkerId = std::uint64_t; | ||||
| 
 | ||||
| struct MarkerInfo | ||||
| { | ||||
|    MarkerInfo(const std::string&        name, | ||||
|               double                    latitude, | ||||
|               double                    longitude, | ||||
|               const std::string         iconName, | ||||
|               boost::gil::rgba8_pixel_t iconColor) : | ||||
|    MarkerInfo(const std::string&               name, | ||||
|               double                           latitude, | ||||
|               double                           longitude, | ||||
|               const std::string&               iconName, | ||||
|               const boost::gil::rgba8_pixel_t& iconColor) : | ||||
|        name {name}, | ||||
|        latitude {latitude}, | ||||
|        longitude {longitude}, | ||||
|  | @ -31,7 +31,7 @@ struct MarkerInfo | |||
|    { | ||||
|    } | ||||
| 
 | ||||
|    MarkerId                  id; | ||||
|    MarkerId                  id{0}; | ||||
|    std::string               name; | ||||
|    double                    latitude; | ||||
|    double                    longitude; | ||||
|  | @ -47,7 +47,21 @@ struct MarkerIconInfo { | |||
|       path{types::GetTexturePath(texture)}, | ||||
|       hotX{hotX}, | ||||
|       hotY{hotY}, | ||||
|       qIcon{QIcon(QString::fromStdString(path))} | ||||
|       qIcon{QIcon(QString::fromStdString(path))}, | ||||
|       image{} | ||||
|    { | ||||
|    } | ||||
| 
 | ||||
|    explicit MarkerIconInfo(const std::string& path, | ||||
|                            std::int32_t       hotX, | ||||
|                            std::int32_t       hotY, | ||||
|                            std::shared_ptr<boost::gil::rgba8_image_t> image) : | ||||
|       name{path}, | ||||
|       path{path}, | ||||
|       hotX{hotX}, | ||||
|       hotY{hotY}, | ||||
|       qIcon{QIcon(QString::fromStdString(path))}, | ||||
|       image{image} | ||||
|    { | ||||
|    } | ||||
| 
 | ||||
|  | @ -56,10 +70,9 @@ struct MarkerIconInfo { | |||
|    std::int32_t hotX; | ||||
|    std::int32_t hotY; | ||||
|    QIcon qIcon; | ||||
|    std::optional<std::shared_ptr<boost::gil::rgba8_image_t>> image; | ||||
| }; | ||||
| 
 | ||||
| const std::vector<MarkerIconInfo>& getMarkerIcons(); | ||||
| 
 | ||||
| } // namespace types
 | ||||
| } // namespace qt
 | ||||
| } // namespace scwx
 | ||||
|  |  | |||
|  | @ -8,7 +8,6 @@ | |||
| #include <scwx/util/logger.hpp> | ||||
| 
 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| #include <QObject> | ||||
| #include <QString> | ||||
|  | @ -16,6 +15,7 @@ | |||
| #include <QPixmap> | ||||
| #include <QColorDialog> | ||||
| #include <QPushButton> | ||||
| #include <QFileDialog> | ||||
| 
 | ||||
| namespace scwx | ||||
| { | ||||
|  | @ -36,6 +36,8 @@ public: | |||
|    } | ||||
| 
 | ||||
|    void show_color_dialog(); | ||||
|    void show_icon_file_dialog(); | ||||
| 
 | ||||
|    void set_icon_color(const std::string& color); | ||||
| 
 | ||||
|    void connect_signals(); | ||||
|  | @ -45,24 +47,20 @@ public: | |||
| 
 | ||||
|    EditMarkerDialog* self_; | ||||
|    QPushButton* deleteButton_; | ||||
|    QIcon get_colored_icon(size_t index, const std::string& color); | ||||
|    QIcon             get_colored_icon(const types::MarkerIconInfo& marker, | ||||
|                                       const std::string&           color); | ||||
| 
 | ||||
|    std::shared_ptr<manager::MarkerManager> markerManager_ = | ||||
|       manager::MarkerManager::Instance(); | ||||
|    const std::vector<types::MarkerIconInfo>* icons_; | ||||
|    types::MarkerId editId_; | ||||
|    bool adding_; | ||||
|    std::string setIconOnAdded_{""}; | ||||
| }; | ||||
| 
 | ||||
| QIcon EditMarkerDialog::Impl::get_colored_icon(size_t             index, | ||||
|                                                const std::string& color) | ||||
| QIcon EditMarkerDialog::Impl::get_colored_icon( | ||||
|    const types::MarkerIconInfo& marker, const std::string& color) | ||||
| { | ||||
|    if (index >= icons_->size()) | ||||
|    { | ||||
|       return QIcon(); | ||||
|    } | ||||
| 
 | ||||
|    return util::modulateColors((*icons_)[index].qIcon, | ||||
|    return util::modulateColors(marker.qIcon, | ||||
|                                self_->ui->iconComboBox->iconSize(), | ||||
|                                QColor(QString::fromStdString(color))); | ||||
| } | ||||
|  | @ -74,12 +72,11 @@ EditMarkerDialog::EditMarkerDialog(QWidget* parent) : | |||
| { | ||||
|    ui->setupUi(this); | ||||
| 
 | ||||
|    p->icons_ = &types::getMarkerIcons(); | ||||
|    for (auto& markerIcon : (*p->icons_)) | ||||
|    for (auto& markerIcon : p->markerManager_->get_icons()) | ||||
|    { | ||||
|       ui->iconComboBox->addItem(markerIcon.qIcon, | ||||
|       ui->iconComboBox->addItem(markerIcon.second.qIcon, | ||||
|                                 QString(""), | ||||
|                                 QString::fromStdString(markerIcon.name)); | ||||
|                                 QString::fromStdString(markerIcon.second.name)); | ||||
|    } | ||||
|    p->deleteButton_ = | ||||
|       ui->buttonBox->addButton("Delete", QDialogButtonBox::DestructiveRole); | ||||
|  | @ -98,7 +95,6 @@ void EditMarkerDialog::setup() | |||
| 
 | ||||
| void EditMarkerDialog::setup(double latitude, double longitude) | ||||
| { | ||||
|    ui->iconComboBox->setCurrentIndex(0); | ||||
|    // By default use foreground color as marker color, mainly so the icons
 | ||||
|    // are vissable in the dropdown menu.
 | ||||
|    QColor color = QWidget::palette().color(QWidget::foregroundRole()); | ||||
|  | @ -106,7 +102,7 @@ void EditMarkerDialog::setup(double latitude, double longitude) | |||
|       "", | ||||
|       latitude, | ||||
|       longitude, | ||||
|       ui->iconComboBox->currentData().toString().toStdString(), | ||||
|       manager::MarkerManager::getDefaultIconName(), | ||||
|       boost::gil::rgba8_pixel_t {static_cast<uint8_t>(color.red()), | ||||
|                                  static_cast<uint8_t>(color.green()), | ||||
|                                  static_cast<uint8_t>(color.blue()), | ||||
|  | @ -128,6 +124,9 @@ void EditMarkerDialog::setup(types::MarkerId id) | |||
|    p->editId_ = id; | ||||
|    p->adding_ = false; | ||||
| 
 | ||||
|    std::string iconColorStr = util::color::ToArgbString(marker->iconColor); | ||||
|    p->set_icon_color(iconColorStr); | ||||
| 
 | ||||
|    int iconIndex = | ||||
|       ui->iconComboBox->findData(QString::fromStdString(marker->iconName)); | ||||
|    if (iconIndex < 0 || marker->iconName == "") | ||||
|  | @ -135,15 +134,11 @@ void EditMarkerDialog::setup(types::MarkerId id) | |||
|       iconIndex = 0; | ||||
|    } | ||||
| 
 | ||||
|    std::string iconColorStr = util::color::ToArgbString(marker->iconColor); | ||||
| 
 | ||||
|    ui->nameLineEdit->setText(QString::fromStdString(marker->name)); | ||||
|    ui->iconComboBox->setCurrentIndex(iconIndex); | ||||
|    ui->latitudeDoubleSpinBox->setValue(marker->latitude); | ||||
|    ui->longitudeDoubleSpinBox->setValue(marker->longitude); | ||||
|    ui->iconColorLineEdit->setText(QString::fromStdString(iconColorStr)); | ||||
| 
 | ||||
|    p->set_icon_color(iconColorStr); | ||||
| } | ||||
| 
 | ||||
| types::MarkerInfo EditMarkerDialog::get_marker_info() const | ||||
|  | @ -163,7 +158,7 @@ types::MarkerInfo EditMarkerDialog::get_marker_info() const | |||
| void EditMarkerDialog::Impl::show_color_dialog() | ||||
| { | ||||
| 
 | ||||
|    QColorDialog* dialog = new QColorDialog(self_); | ||||
|    auto* dialog = new QColorDialog(self_); | ||||
| 
 | ||||
|    dialog->setAttribute(Qt::WA_DeleteOnClose); | ||||
|    dialog->setOption(QColorDialog::ColorDialogOption::ShowAlphaChannel); | ||||
|  | @ -187,6 +182,28 @@ void EditMarkerDialog::Impl::show_color_dialog() | |||
|    dialog->open(); | ||||
| } | ||||
| 
 | ||||
| void EditMarkerDialog::Impl::show_icon_file_dialog() | ||||
| { | ||||
| 
 | ||||
|    auto* dialog = new QFileDialog(self_); | ||||
| 
 | ||||
|    dialog->setFileMode(QFileDialog::ExistingFile); | ||||
|    dialog->setNameFilters({"Icon (*.png *.svg)", "All (*)"}); | ||||
|    dialog->setAttribute(Qt::WA_DeleteOnClose); | ||||
| 
 | ||||
|    QObject::connect(dialog, | ||||
|                     &QFileDialog::fileSelected, | ||||
|                     self_, | ||||
|                     [this](const QString& file) | ||||
|                     { | ||||
|                        std::string path = | ||||
|                           QDir::toNativeSeparators(file).toStdString(); | ||||
|                        setIconOnAdded_ = path; | ||||
|                        markerManager_->add_icon(path); | ||||
|                     }); | ||||
|    dialog->open(); | ||||
| } | ||||
| 
 | ||||
| void EditMarkerDialog::Impl::connect_signals() | ||||
| { | ||||
|    connect(self_, | ||||
|  | @ -217,7 +234,33 @@ void EditMarkerDialog::Impl::connect_signals() | |||
|    connect(self_->ui->iconColorButton, | ||||
|            &QAbstractButton::clicked, | ||||
|            self_, | ||||
|            [=, this]() { self_->p->show_color_dialog(); }); | ||||
|            [=, this]() { show_color_dialog(); }); | ||||
| 
 | ||||
|    connect(self_->ui->iconFileOpenButton, | ||||
|            &QPushButton::clicked, | ||||
|            self_, | ||||
|            [this]() { show_icon_file_dialog(); }); | ||||
| 
 | ||||
|    connect(markerManager_.get(), | ||||
|            &manager::MarkerManager::IconAdded, | ||||
|            self_, | ||||
|            [this]() | ||||
|            { | ||||
|               std::string color = | ||||
|                  self_->ui->iconColorLineEdit->text().toStdString(); | ||||
|               set_icon_color(color); | ||||
| 
 | ||||
|               if (setIconOnAdded_ != "") | ||||
|               { | ||||
|                  int i = self_->ui->iconComboBox->findData( | ||||
|                     QString::fromStdString(setIconOnAdded_)); | ||||
|                  if (i >= 0) | ||||
|                  { | ||||
|                     self_->ui->iconComboBox->setCurrentIndex(i); | ||||
|                     setIconOnAdded_ = ""; | ||||
|                  } | ||||
|               } | ||||
|            }); | ||||
| } | ||||
| 
 | ||||
| void EditMarkerDialog::Impl::set_icon_color(const std::string& color) | ||||
|  | @ -225,10 +268,25 @@ void EditMarkerDialog::Impl::set_icon_color(const std::string& color) | |||
|    self_->ui->iconColorFrame->setStyleSheet( | ||||
|       QString::fromStdString(fmt::format("background-color: {}", color))); | ||||
| 
 | ||||
|    for (size_t i = 0; i < icons_->size(); i++) | ||||
|    auto* iconComboBox = self_->ui->iconComboBox; | ||||
| 
 | ||||
| 
 | ||||
|    QVariant data = self_->ui->iconComboBox->currentData(); | ||||
|    self_->ui->iconComboBox->clear(); | ||||
|    for (auto& markerIcon : markerManager_->get_icons()) | ||||
|    { | ||||
|       self_->ui->iconComboBox->setItemIcon(static_cast<int>(i), | ||||
|                                            get_colored_icon(i, color)); | ||||
|       int i = | ||||
|          iconComboBox->findData(QString::fromStdString(markerIcon.second.name)); | ||||
|       QIcon icon = get_colored_icon(markerIcon.second, color); | ||||
|       if (i < 0) | ||||
|       { | ||||
|          iconComboBox->addItem( | ||||
|             icon, QString(""), QString::fromStdString(markerIcon.second.name)); | ||||
|       } | ||||
|       else | ||||
|       { | ||||
|          self_->ui->iconComboBox->setItemIcon(i, icon); | ||||
|       } | ||||
|    } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ class EditMarkerDialog : public QDialog | |||
| 
 | ||||
| public: | ||||
|    explicit EditMarkerDialog(QWidget* parent = nullptr); | ||||
|    ~EditMarkerDialog(); | ||||
|    ~EditMarkerDialog() override; | ||||
| 
 | ||||
|    void setup(); | ||||
|    void setup(double latitude, double longitude); | ||||
|  |  | |||
|  | @ -7,88 +7,14 @@ | |||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>400</width> | ||||
|     <height>211</height> | ||||
|     <height>249</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|    <string>Edit Location Marker</string> | ||||
|   </property> | ||||
|   <layout class="QGridLayout" name="gridLayout"> | ||||
|    <item row="2" column="0"> | ||||
|     <widget class="QLabel" name="label_4"> | ||||
|      <property name="text"> | ||||
|       <string>Icon</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="6" column="0" colspan="2"> | ||||
|     <widget class="QDialogButtonBox" name="buttonBox"> | ||||
|      <property name="orientation"> | ||||
|       <enum>Qt::Orientation::Horizontal</enum> | ||||
|      </property> | ||||
|      <property name="standardButtons"> | ||||
|       <set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="2" column="1"> | ||||
|     <widget class="QComboBox" name="iconComboBox"> | ||||
|      <property name="autoFillBackground"> | ||||
|       <bool>true</bool> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="0" column="0"> | ||||
|     <widget class="QLabel" name="label_2"> | ||||
|      <property name="text"> | ||||
|       <string>Latitude</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="1" column="1"> | ||||
|     <widget class="QDoubleSpinBox" name="longitudeDoubleSpinBox"> | ||||
|      <property name="decimals"> | ||||
|       <number>4</number> | ||||
|      </property> | ||||
|      <property name="minimum"> | ||||
|       <double>-180.000000000000000</double> | ||||
|      </property> | ||||
|      <property name="maximum"> | ||||
|       <double>180.000000000000000</double> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="4" column="1"> | ||||
|     <widget class="QLineEdit" name="nameLineEdit"/> | ||||
|    </item> | ||||
|    <item row="4" column="0"> | ||||
|     <widget class="QLabel" name="label"> | ||||
|      <property name="text"> | ||||
|       <string>Name</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="0" column="1"> | ||||
|     <widget class="QDoubleSpinBox" name="latitudeDoubleSpinBox"> | ||||
|      <property name="decimals"> | ||||
|       <number>4</number> | ||||
|      </property> | ||||
|      <property name="minimum"> | ||||
|       <double>-90.000000000000000</double> | ||||
|      </property> | ||||
|      <property name="maximum"> | ||||
|       <double>90.000000000000000</double> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="1" column="0"> | ||||
|     <widget class="QLabel" name="label_3"> | ||||
|      <property name="text"> | ||||
|       <string>Longitude</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="5" column="0"> | ||||
|    <item row="9" column="0"> | ||||
|     <spacer name="verticalSpacer"> | ||||
|      <property name="orientation"> | ||||
|       <enum>Qt::Orientation::Vertical</enum> | ||||
|  | @ -101,14 +27,7 @@ | |||
|      </property> | ||||
|     </spacer> | ||||
|    </item> | ||||
|    <item row="3" column="0"> | ||||
|     <widget class="QLabel" name="label_5"> | ||||
|      <property name="text"> | ||||
|       <string>Icon Color</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="3" column="1"> | ||||
|    <item row="4" column="2"> | ||||
|     <layout class="QHBoxLayout" name="horizontalLayout"> | ||||
|      <item> | ||||
|       <widget class="QFrame" name="iconColorFrame"> | ||||
|  | @ -146,6 +65,103 @@ | |||
|      </item> | ||||
|     </layout> | ||||
|    </item> | ||||
|    <item row="0" column="2"> | ||||
|     <widget class="QDoubleSpinBox" name="latitudeDoubleSpinBox"> | ||||
|      <property name="decimals"> | ||||
|       <number>4</number> | ||||
|      </property> | ||||
|      <property name="minimum"> | ||||
|       <double>-90.000000000000000</double> | ||||
|      </property> | ||||
|      <property name="maximum"> | ||||
|       <double>90.000000000000000</double> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="5" column="0"> | ||||
|     <widget class="QLabel" name="label"> | ||||
|      <property name="text"> | ||||
|       <string>Name</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="3" column="0"> | ||||
|     <widget class="QLabel" name="label_4"> | ||||
|      <property name="text"> | ||||
|       <string>Icon</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="10" column="0" colspan="3"> | ||||
|     <widget class="QDialogButtonBox" name="buttonBox"> | ||||
|      <property name="orientation"> | ||||
|       <enum>Qt::Orientation::Horizontal</enum> | ||||
|      </property> | ||||
|      <property name="standardButtons"> | ||||
|       <set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="1" column="0"> | ||||
|     <widget class="QLabel" name="label_3"> | ||||
|      <property name="text"> | ||||
|       <string>Longitude</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="4" column="0"> | ||||
|     <widget class="QLabel" name="label_5"> | ||||
|      <property name="text"> | ||||
|       <string>Icon Color</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="0" column="0"> | ||||
|     <widget class="QLabel" name="label_2"> | ||||
|      <property name="text"> | ||||
|       <string>Latitude</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="3" column="3"> | ||||
|     <widget class="QToolButton" name="iconFileOpenButton"> | ||||
|      <property name="toolTip"> | ||||
|       <string>Add Custom Icon</string> | ||||
|      </property> | ||||
|      <property name="text"> | ||||
|       <string>...</string> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="1" column="2"> | ||||
|     <widget class="QDoubleSpinBox" name="longitudeDoubleSpinBox"> | ||||
|      <property name="decimals"> | ||||
|       <number>4</number> | ||||
|      </property> | ||||
|      <property name="minimum"> | ||||
|       <double>-180.000000000000000</double> | ||||
|      </property> | ||||
|      <property name="maximum"> | ||||
|       <double>180.000000000000000</double> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item row="5" column="2"> | ||||
|     <widget class="QLineEdit" name="nameLineEdit"/> | ||||
|    </item> | ||||
|    <item row="3" column="2"> | ||||
|     <widget class="QComboBox" name="iconComboBox"> | ||||
|      <property name="sizePolicy"> | ||||
|       <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||||
|        <horstretch>0</horstretch> | ||||
|        <verstretch>0</verstretch> | ||||
|       </sizepolicy> | ||||
|      </property> | ||||
|      <property name="autoFillBackground"> | ||||
|       <bool>true</bool> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <resources> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 AdenKoperczak
						AdenKoperczak