mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 13:10:04 +00:00 
			
		
		
		
	Save (works) and reload (doesn't work) placefiles from settings
This commit is contained in:
		
							parent
							
								
									ad5c2b583d
								
							
						
					
					
						commit
						6f14745a59
					
				
					 3 changed files with 158 additions and 18 deletions
				
			
		|  | @ -1,5 +1,6 @@ | ||||||
| #include <scwx/qt/manager/placefile_manager.hpp> | #include <scwx/qt/manager/placefile_manager.hpp> | ||||||
| #include <scwx/qt/manager/resource_manager.hpp> | #include <scwx/qt/manager/resource_manager.hpp> | ||||||
|  | #include <scwx/qt/util/json.hpp> | ||||||
| #include <scwx/qt/util/network.hpp> | #include <scwx/qt/util/network.hpp> | ||||||
| #include <scwx/gr/placefile.hpp> | #include <scwx/gr/placefile.hpp> | ||||||
| #include <scwx/network/cpr.hpp> | #include <scwx/network/cpr.hpp> | ||||||
|  | @ -11,11 +12,13 @@ | ||||||
| #include <QDir> | #include <QDir> | ||||||
| #include <QGuiApplication> | #include <QGuiApplication> | ||||||
| #include <QScreen> | #include <QScreen> | ||||||
|  | #include <QStandardPaths> | ||||||
| #include <QUrl> | #include <QUrl> | ||||||
| #include <boost/algorithm/string.hpp> | #include <boost/algorithm/string.hpp> | ||||||
| #include <boost/asio/post.hpp> | #include <boost/asio/post.hpp> | ||||||
| #include <boost/asio/steady_timer.hpp> | #include <boost/asio/steady_timer.hpp> | ||||||
| #include <boost/asio/thread_pool.hpp> | #include <boost/asio/thread_pool.hpp> | ||||||
|  | #include <boost/json.hpp> | ||||||
| #include <boost/tokenizer.hpp> | #include <boost/tokenizer.hpp> | ||||||
| #include <cpr/cpr.h> | #include <cpr/cpr.h> | ||||||
| 
 | 
 | ||||||
|  | @ -29,6 +32,11 @@ namespace manager | ||||||
| static const std::string logPrefix_ = "scwx::qt::manager::placefile_manager"; | static const std::string logPrefix_ = "scwx::qt::manager::placefile_manager"; | ||||||
| static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||||
| 
 | 
 | ||||||
|  | static const std::string kEnabledName_     = "enabled"; | ||||||
|  | static const std::string kThresholdedName_ = "thresholded"; | ||||||
|  | static const std::string kTitleName_       = "title"; | ||||||
|  | static const std::string kNameName_        = "name"; | ||||||
|  | 
 | ||||||
| class PlacefileManager::Impl | class PlacefileManager::Impl | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  | @ -37,12 +45,18 @@ public: | ||||||
|    explicit Impl(PlacefileManager* self) : self_ {self} {} |    explicit Impl(PlacefileManager* self) : self_ {self} {} | ||||||
|    ~Impl() {} |    ~Impl() {} | ||||||
| 
 | 
 | ||||||
|  |    void InitializePlacefileSettings(); | ||||||
|  |    void ReadPlacefileSettings(); | ||||||
|  |    void WritePlacefileSettings(); | ||||||
|  | 
 | ||||||
|    static void LoadResources(const std::shared_ptr<gr::Placefile>& placefile); |    static void LoadResources(const std::shared_ptr<gr::Placefile>& placefile); | ||||||
| 
 | 
 | ||||||
|    boost::asio::thread_pool threadPool_ {1u}; |    boost::asio::thread_pool threadPool_ {1u}; | ||||||
| 
 | 
 | ||||||
|    PlacefileManager* self_; |    PlacefileManager* self_; | ||||||
| 
 | 
 | ||||||
|  |    std::string placefileSettingsPath_ {}; | ||||||
|  | 
 | ||||||
|    std::shared_ptr<config::RadarSite> radarSite_ {}; |    std::shared_ptr<config::RadarSite> radarSite_ {}; | ||||||
| 
 | 
 | ||||||
|    std::vector<std::shared_ptr<PlacefileRecord>> placefileRecords_ {}; |    std::vector<std::shared_ptr<PlacefileRecord>> placefileRecords_ {}; | ||||||
|  | @ -57,8 +71,15 @@ public: | ||||||
|    explicit PlacefileRecord(Impl*                          impl, |    explicit PlacefileRecord(Impl*                          impl, | ||||||
|                             const std::string&             name, |                             const std::string&             name, | ||||||
|                             std::shared_ptr<gr::Placefile> placefile, |                             std::shared_ptr<gr::Placefile> placefile, | ||||||
|                             bool                           enabled = true) : |                             const std::string&             title   = {}, | ||||||
|        p {impl}, name_ {name}, placefile_ {placefile}, enabled_ {enabled} |                             bool                           enabled = false, | ||||||
|  |                             bool thresholded                       = false) : | ||||||
|  |        p {impl}, | ||||||
|  |        name_ {name}, | ||||||
|  |        placefile_ {placefile}, | ||||||
|  |        title_ {title}, | ||||||
|  |        enabled_ {enabled}, | ||||||
|  |        thresholded_ {thresholded} | ||||||
|    { |    { | ||||||
|    } |    } | ||||||
|    ~PlacefileRecord() |    ~PlacefileRecord() | ||||||
|  | @ -71,19 +92,56 @@ public: | ||||||
|    void UpdateAsync(); |    void UpdateAsync(); | ||||||
|    void UpdatePlacefile(const std::shared_ptr<gr::Placefile>& placefile); |    void UpdatePlacefile(const std::shared_ptr<gr::Placefile>& placefile); | ||||||
| 
 | 
 | ||||||
|  |    friend void tag_invoke(boost::json::value_from_tag, | ||||||
|  |                           boost::json::value&                     jv, | ||||||
|  |                           const std::shared_ptr<PlacefileRecord>& record) | ||||||
|  |    { | ||||||
|  |       jv = {{kEnabledName_, record->enabled_}, | ||||||
|  |             {kThresholdedName_, record->thresholded_}, | ||||||
|  |             {kTitleName_, record->title_}, | ||||||
|  |             {kNameName_, record->name_}}; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    friend PlacefileRecord tag_invoke(boost::json::value_to_tag<PlacefileRecord>, | ||||||
|  |                                      const boost::json::value& jv) | ||||||
|  |    { | ||||||
|  |       return PlacefileRecord { | ||||||
|  |          nullptr, | ||||||
|  |          boost::json::value_to<std::string>(jv.at(kNameName_)), | ||||||
|  |          nullptr, | ||||||
|  |          boost::json::value_to<std::string>(jv.at(kTitleName_)), | ||||||
|  |          jv.at(kEnabledName_).as_bool(), | ||||||
|  |          jv.at(kThresholdedName_).as_bool()}; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|    Impl* p; |    Impl* p; | ||||||
| 
 | 
 | ||||||
|    std::string                    name_; |    std::string                    name_; | ||||||
|  |    std::string                    title_; | ||||||
|    std::shared_ptr<gr::Placefile> placefile_; |    std::shared_ptr<gr::Placefile> placefile_; | ||||||
|    bool                           enabled_; |    bool                           enabled_; | ||||||
|    bool                           thresholded_ {false}; |    bool                           thresholded_; | ||||||
|    boost::asio::thread_pool       threadPool_ {1u}; |    boost::asio::thread_pool       threadPool_ {1u}; | ||||||
|    boost::asio::steady_timer      refreshTimer_ {threadPool_}; |    boost::asio::steady_timer      refreshTimer_ {threadPool_}; | ||||||
|    std::mutex                     refreshMutex_ {}; |    std::mutex                     refreshMutex_ {}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| PlacefileManager::PlacefileManager() : p(std::make_unique<Impl>(this)) {} | PlacefileManager::PlacefileManager() : p(std::make_unique<Impl>(this)) | ||||||
| PlacefileManager::~PlacefileManager() = default; | { | ||||||
|  |    boost::asio::post(p->threadPool_, | ||||||
|  |                      [this]() | ||||||
|  |                      { | ||||||
|  |                         // Read placefile settings on startup
 | ||||||
|  |                         p->InitializePlacefileSettings(); | ||||||
|  |                         p->ReadPlacefileSettings(); | ||||||
|  |                      }); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | PlacefileManager::~PlacefileManager() | ||||||
|  | { | ||||||
|  |    // Write placefile settings on shutdown
 | ||||||
|  |    p->WritePlacefileSettings(); | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| bool PlacefileManager::placefile_enabled(const std::string& name) | bool PlacefileManager::placefile_enabled(const std::string& name) | ||||||
| { | { | ||||||
|  | @ -109,6 +167,18 @@ bool PlacefileManager::placefile_thresholded(const std::string& name) | ||||||
|    return false; |    return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::string PlacefileManager::placefile_title(const std::string& name) | ||||||
|  | { | ||||||
|  |    std::shared_lock lock(p->placefileRecordLock_); | ||||||
|  | 
 | ||||||
|  |    auto it = p->placefileRecordMap_.find(name); | ||||||
|  |    if (it != p->placefileRecordMap_.cend()) | ||||||
|  |    { | ||||||
|  |       return it->second->title_; | ||||||
|  |    } | ||||||
|  |    return {}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| std::shared_ptr<gr::Placefile> | std::shared_ptr<gr::Placefile> | ||||||
| PlacefileManager::placefile(const std::string& name) | PlacefileManager::placefile(const std::string& name) | ||||||
| { | { | ||||||
|  | @ -189,6 +259,71 @@ void PlacefileManager::set_placefile_url(const std::string& name, | ||||||
|    } |    } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void PlacefileManager::Impl::InitializePlacefileSettings() | ||||||
|  | { | ||||||
|  |    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); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    placefileSettingsPath_ = appDataPath + "/placefiles.json"; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PlacefileManager::Impl::ReadPlacefileSettings() | ||||||
|  | { | ||||||
|  |    logger_->info("Reading placefile settings"); | ||||||
|  | 
 | ||||||
|  |    boost::json::value placefileJson = nullptr; | ||||||
|  | 
 | ||||||
|  |    // Determine if placefile settings exists
 | ||||||
|  |    if (std::filesystem::exists(placefileSettingsPath_)) | ||||||
|  |    { | ||||||
|  |       placefileJson = util::json::ReadJsonFile(placefileSettingsPath_); | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    // If placefile settings was successfully read
 | ||||||
|  |    if (placefileJson != nullptr && placefileJson.is_array()) | ||||||
|  |    { | ||||||
|  |       // For each placefile entry
 | ||||||
|  |       auto& placefileArray = placefileJson.as_array(); | ||||||
|  |       for (auto& placefileEntry : placefileArray) | ||||||
|  |       { | ||||||
|  |          try | ||||||
|  |          { | ||||||
|  |             // Convert placefile entry to a record
 | ||||||
|  |             PlacefileRecord record = | ||||||
|  |                boost::json::value_to<PlacefileRecord>(placefileEntry); | ||||||
|  | 
 | ||||||
|  |             self_->AddUrl(record.name_, | ||||||
|  |                           record.title_, | ||||||
|  |                           record.enabled_, | ||||||
|  |                           record.thresholded_); | ||||||
|  |          } | ||||||
|  |          catch (const std::exception& ex) | ||||||
|  |          { | ||||||
|  |             logger_->warn("Invalid placefile entry: {}", ex.what()); | ||||||
|  |          } | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void PlacefileManager::Impl::WritePlacefileSettings() | ||||||
|  | { | ||||||
|  |    logger_->info("Saving placefile settings"); | ||||||
|  | 
 | ||||||
|  |    std::shared_lock lock {placefileRecordLock_}; | ||||||
|  |    auto             placefileJson = boost::json::value_from(placefileRecords_); | ||||||
|  |    util::json::WriteJsonFile(placefileSettingsPath_, placefileJson); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void PlacefileManager::SetRadarSite( | void PlacefileManager::SetRadarSite( | ||||||
|    std::shared_ptr<config::RadarSite> radarSite) |    std::shared_ptr<config::RadarSite> radarSite) | ||||||
| { | { | ||||||
|  | @ -231,7 +366,10 @@ PlacefileManager::GetActivePlacefiles() | ||||||
|    return placefiles; |    return placefiles; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void PlacefileManager::AddUrl(const std::string& urlString) | void PlacefileManager::AddUrl(const std::string& urlString, | ||||||
|  |                               const std::string& title, | ||||||
|  |                               bool               enabled, | ||||||
|  |                               bool               thresholded) | ||||||
| { | { | ||||||
|    std::string normalizedUrl = util::network::NormalizeUrl(urlString); |    std::string normalizedUrl = util::network::NormalizeUrl(urlString); | ||||||
| 
 | 
 | ||||||
|  | @ -254,7 +392,7 @@ void PlacefileManager::AddUrl(const std::string& urlString) | ||||||
|    // Add an empty placefile record for the new URL
 |    // Add an empty placefile record for the new URL
 | ||||||
|    auto& record = |    auto& record = | ||||||
|       p->placefileRecords_.emplace_back(std::make_shared<Impl::PlacefileRecord>( |       p->placefileRecords_.emplace_back(std::make_shared<Impl::PlacefileRecord>( | ||||||
|          p.get(), normalizedUrl, nullptr, false)); |          p.get(), normalizedUrl, nullptr, title, enabled, thresholded)); | ||||||
|    p->placefileRecordMap_.insert_or_assign(normalizedUrl, record); |    p->placefileRecordMap_.insert_or_assign(normalizedUrl, record); | ||||||
| 
 | 
 | ||||||
|    lock.unlock(); |    lock.unlock(); | ||||||
|  | @ -303,7 +441,7 @@ void PlacefileManager::LoadFile(const std::string& filename) | ||||||
|             // If this is a new placefile, add it
 |             // If this is a new placefile, add it
 | ||||||
|             auto& record = p->placefileRecords_.emplace_back( |             auto& record = p->placefileRecords_.emplace_back( | ||||||
|                std::make_shared<Impl::PlacefileRecord>( |                std::make_shared<Impl::PlacefileRecord>( | ||||||
|                   p.get(), placefileName, placefile)); |                   p.get(), placefileName, placefile, placefile->title(), true)); | ||||||
|             p->placefileRecordMap_.insert_or_assign(placefileName, record); |             p->placefileRecordMap_.insert_or_assign(placefileName, record); | ||||||
| 
 | 
 | ||||||
|             lock.unlock(); |             lock.unlock(); | ||||||
|  | @ -434,6 +572,7 @@ void PlacefileManager::Impl::PlacefileRecord::Update() | ||||||
|       { |       { | ||||||
|          // Update the placefile
 |          // Update the placefile
 | ||||||
|          placefile_ = updatedPlacefile; |          placefile_ = updatedPlacefile; | ||||||
|  |          title_     = placefile_->title(); | ||||||
| 
 | 
 | ||||||
|          // Notify slots of the placefile update
 |          // Notify slots of the placefile update
 | ||||||
|          Q_EMIT p->self_->PlacefileUpdated(name); |          Q_EMIT p->self_->PlacefileUpdated(name); | ||||||
|  |  | ||||||
|  | @ -22,6 +22,7 @@ public: | ||||||
| 
 | 
 | ||||||
|    bool        placefile_enabled(const std::string& name); |    bool        placefile_enabled(const std::string& name); | ||||||
|    bool        placefile_thresholded(const std::string& name); |    bool        placefile_thresholded(const std::string& name); | ||||||
|  |    std::string placefile_title(const std::string& name); | ||||||
|    std::shared_ptr<gr::Placefile> placefile(const std::string& name); |    std::shared_ptr<gr::Placefile> placefile(const std::string& name); | ||||||
| 
 | 
 | ||||||
|    void set_placefile_enabled(const std::string& name, bool enabled); |    void set_placefile_enabled(const std::string& name, bool enabled); | ||||||
|  | @ -37,7 +38,10 @@ public: | ||||||
|     */ |     */ | ||||||
|    std::vector<std::shared_ptr<gr::Placefile>> GetActivePlacefiles(); |    std::vector<std::shared_ptr<gr::Placefile>> GetActivePlacefiles(); | ||||||
| 
 | 
 | ||||||
|    void AddUrl(const std::string& urlString); |    void AddUrl(const std::string& urlString, | ||||||
|  |                const std::string& title       = {}, | ||||||
|  |                bool               enabled     = false, | ||||||
|  |                bool               thresholded = false); | ||||||
|    void LoadFile(const std::string& filename); |    void LoadFile(const std::string& filename); | ||||||
|    void RemoveUrl(const std::string& urlString); |    void RemoveUrl(const std::string& urlString); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -159,15 +159,12 @@ QVariant PlacefileModel::data(const QModelIndex& index, int role) const | ||||||
|           role == Qt::ItemDataRole::ToolTipRole) |           role == Qt::ItemDataRole::ToolTipRole) | ||||||
|       { |       { | ||||||
|          std::string description = placefileName; |          std::string description = placefileName; | ||||||
|          auto        placefile = p->placefileManager_->placefile(placefileName); |          std::string title = | ||||||
|          if (placefile != nullptr) |             p->placefileManager_->placefile_title(placefileName); | ||||||
|          { |  | ||||||
|             std::string title = placefile->title(); |  | ||||||
|          if (!title.empty()) |          if (!title.empty()) | ||||||
|          { |          { | ||||||
|             description = title + '\n' + description; |             description = title + '\n' + description; | ||||||
|          } |          } | ||||||
|          } |  | ||||||
| 
 | 
 | ||||||
|          return QString::fromStdString(description); |          return QString::fromStdString(description); | ||||||
|       } |       } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat