mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 04:10:06 +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/resource_manager.hpp> | ||||
| #include <scwx/qt/util/json.hpp> | ||||
| #include <scwx/qt/util/network.hpp> | ||||
| #include <scwx/gr/placefile.hpp> | ||||
| #include <scwx/network/cpr.hpp> | ||||
|  | @ -11,11 +12,13 @@ | |||
| #include <QDir> | ||||
| #include <QGuiApplication> | ||||
| #include <QScreen> | ||||
| #include <QStandardPaths> | ||||
| #include <QUrl> | ||||
| #include <boost/algorithm/string.hpp> | ||||
| #include <boost/asio/post.hpp> | ||||
| #include <boost/asio/steady_timer.hpp> | ||||
| #include <boost/asio/thread_pool.hpp> | ||||
| #include <boost/json.hpp> | ||||
| #include <boost/tokenizer.hpp> | ||||
| #include <cpr/cpr.h> | ||||
| 
 | ||||
|  | @ -29,6 +32,11 @@ namespace manager | |||
| static const std::string logPrefix_ = "scwx::qt::manager::placefile_manager"; | ||||
| static const auto        logger_    = scwx::util::Logger::Create(logPrefix_); | ||||
| 
 | ||||
| static const std::string kEnabledName_     = "enabled"; | ||||
| static const std::string kThresholdedName_ = "thresholded"; | ||||
| static const std::string kTitleName_       = "title"; | ||||
| static const std::string kNameName_        = "name"; | ||||
| 
 | ||||
| class PlacefileManager::Impl | ||||
| { | ||||
| public: | ||||
|  | @ -37,12 +45,18 @@ public: | |||
|    explicit Impl(PlacefileManager* self) : self_ {self} {} | ||||
|    ~Impl() {} | ||||
| 
 | ||||
|    void InitializePlacefileSettings(); | ||||
|    void ReadPlacefileSettings(); | ||||
|    void WritePlacefileSettings(); | ||||
| 
 | ||||
|    static void LoadResources(const std::shared_ptr<gr::Placefile>& placefile); | ||||
| 
 | ||||
|    boost::asio::thread_pool threadPool_ {1u}; | ||||
| 
 | ||||
|    PlacefileManager* self_; | ||||
| 
 | ||||
|    std::string placefileSettingsPath_ {}; | ||||
| 
 | ||||
|    std::shared_ptr<config::RadarSite> radarSite_ {}; | ||||
| 
 | ||||
|    std::vector<std::shared_ptr<PlacefileRecord>> placefileRecords_ {}; | ||||
|  | @ -57,8 +71,15 @@ public: | |||
|    explicit PlacefileRecord(Impl*                          impl, | ||||
|                             const std::string&             name, | ||||
|                             std::shared_ptr<gr::Placefile> placefile, | ||||
|                             bool                           enabled = true) : | ||||
|        p {impl}, name_ {name}, placefile_ {placefile}, enabled_ {enabled} | ||||
|                             const std::string&             title   = {}, | ||||
|                             bool                           enabled = false, | ||||
|                             bool thresholded                       = false) : | ||||
|        p {impl}, | ||||
|        name_ {name}, | ||||
|        placefile_ {placefile}, | ||||
|        title_ {title}, | ||||
|        enabled_ {enabled}, | ||||
|        thresholded_ {thresholded} | ||||
|    { | ||||
|    } | ||||
|    ~PlacefileRecord() | ||||
|  | @ -71,19 +92,56 @@ public: | |||
|    void UpdateAsync(); | ||||
|    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; | ||||
| 
 | ||||
|    std::string                    name_; | ||||
|    std::string                    title_; | ||||
|    std::shared_ptr<gr::Placefile> placefile_; | ||||
|    bool                           enabled_; | ||||
|    bool                           thresholded_ {false}; | ||||
|    bool                           thresholded_; | ||||
|    boost::asio::thread_pool       threadPool_ {1u}; | ||||
|    boost::asio::steady_timer      refreshTimer_ {threadPool_}; | ||||
|    std::mutex                     refreshMutex_ {}; | ||||
| }; | ||||
| 
 | ||||
| PlacefileManager::PlacefileManager() : p(std::make_unique<Impl>(this)) {} | ||||
| PlacefileManager::~PlacefileManager() = default; | ||||
| PlacefileManager::PlacefileManager() : p(std::make_unique<Impl>(this)) | ||||
| { | ||||
|    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) | ||||
| { | ||||
|  | @ -109,6 +167,18 @@ bool PlacefileManager::placefile_thresholded(const std::string& name) | |||
|    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> | ||||
| 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( | ||||
|    std::shared_ptr<config::RadarSite> radarSite) | ||||
| { | ||||
|  | @ -231,7 +366,10 @@ PlacefileManager::GetActivePlacefiles() | |||
|    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); | ||||
| 
 | ||||
|  | @ -254,7 +392,7 @@ void PlacefileManager::AddUrl(const std::string& urlString) | |||
|    // Add an empty placefile record for the new URL
 | ||||
|    auto& record = | ||||
|       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); | ||||
| 
 | ||||
|    lock.unlock(); | ||||
|  | @ -303,7 +441,7 @@ void PlacefileManager::LoadFile(const std::string& filename) | |||
|             // If this is a new placefile, add it
 | ||||
|             auto& record = p->placefileRecords_.emplace_back( | ||||
|                std::make_shared<Impl::PlacefileRecord>( | ||||
|                   p.get(), placefileName, placefile)); | ||||
|                   p.get(), placefileName, placefile, placefile->title(), true)); | ||||
|             p->placefileRecordMap_.insert_or_assign(placefileName, record); | ||||
| 
 | ||||
|             lock.unlock(); | ||||
|  | @ -434,6 +572,7 @@ void PlacefileManager::Impl::PlacefileRecord::Update() | |||
|       { | ||||
|          // Update the placefile
 | ||||
|          placefile_ = updatedPlacefile; | ||||
|          title_     = placefile_->title(); | ||||
| 
 | ||||
|          // Notify slots of the placefile update
 | ||||
|          Q_EMIT p->self_->PlacefileUpdated(name); | ||||
|  |  | |||
|  | @ -20,8 +20,9 @@ public: | |||
|    explicit PlacefileManager(); | ||||
|    ~PlacefileManager(); | ||||
| 
 | ||||
|    bool placefile_enabled(const std::string& name); | ||||
|    bool placefile_thresholded(const std::string& name); | ||||
|    bool        placefile_enabled(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); | ||||
| 
 | ||||
|    void set_placefile_enabled(const std::string& name, bool enabled); | ||||
|  | @ -37,7 +38,10 @@ public: | |||
|     */ | ||||
|    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 RemoveUrl(const std::string& urlString); | ||||
| 
 | ||||
|  |  | |||
|  | @ -159,14 +159,11 @@ QVariant PlacefileModel::data(const QModelIndex& index, int role) const | |||
|           role == Qt::ItemDataRole::ToolTipRole) | ||||
|       { | ||||
|          std::string description = placefileName; | ||||
|          auto        placefile = p->placefileManager_->placefile(placefileName); | ||||
|          if (placefile != nullptr) | ||||
|          std::string title = | ||||
|             p->placefileManager_->placefile_title(placefileName); | ||||
|          if (!title.empty()) | ||||
|          { | ||||
|             std::string title = placefile->title(); | ||||
|             if (!title.empty()) | ||||
|             { | ||||
|                description = title + '\n' + description; | ||||
|             } | ||||
|             description = title + '\n' + description; | ||||
|          } | ||||
| 
 | ||||
|          return QString::fromStdString(description); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat