Add working poi manager implementation

This commit is contained in:
AdenKoperczak 2024-10-04 16:42:54 -04:00
parent ec4387112e
commit f5d867cf1a
2 changed files with 191 additions and 13 deletions

View file

@ -1,9 +1,14 @@
#include <scwx/qt/manager/poi_manager.hpp> #include <scwx/qt/manager/poi_manager.hpp>
#include <scwx/util/logger.hpp> #include <scwx/qt/types/poi_types.hpp>
#include <scwx/qt/util/json.hpp> #include <scwx/qt/util/json.hpp>
#include <scwx/qt/main/application.hpp>
#include <scwx/util/logger.hpp>
#include <filesystem> #include <filesystem>
#include <vector>
#include <string>
#include <QStandardPaths>
#include <boost/json.hpp> #include <boost/json.hpp>
namespace scwx namespace scwx
@ -13,7 +18,7 @@ namespace qt
namespace manager namespace manager
{ {
static const std::string logPrefix_ = "scwx::qt::manager::placefile_manager"; static const std::string logPrefix_ = "scwx::qt::manager::poi_manager";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_); static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
static const std::string kNameName_ = "name"; static const std::string kNameName_ = "name";
@ -23,22 +28,27 @@ static const std::string kLongitudeName_ = "longitude";
class POIManager::Impl class POIManager::Impl
{ {
public: public:
class PointOfInterest; class POIRecord;
explicit Impl(POIManager* self) : self_ {self} {} explicit Impl(POIManager* self) : self_ {self} {}
~Impl() {}
std::string poiSettingsPath_ {}; std::string poiSettingsPath_ {};
std::vector<std::shared_ptr<POIRecord>> poiRecords_ {};
POIManager* self_; POIManager* self_;
void InitializePOISettings();
void ReadPOISettings(); void ReadPOISettings();
void WritePOISettings();
std::shared_ptr<POIRecord> GetPOIByName(const std::string& name);
}; };
class POIManager::Impl::PointOfInterest class POIManager::Impl::POIRecord
{ {
public: public:
PointOfInterest(std::string name, double latitude, double longitude) : POIRecord(std::string name, double latitude, double longitude) :
name_ {name}, latitude_ {latitude}, longitude_ {longitude} name_ {name}, latitude_ {latitude}, longitude_ {longitude}
{ {
} }
@ -49,28 +59,45 @@ public:
friend void tag_invoke(boost::json::value_from_tag, friend void tag_invoke(boost::json::value_from_tag,
boost::json::value& jv, boost::json::value& jv,
const std::shared_ptr<PointOfInterest>& record) const std::shared_ptr<POIRecord>& record)
{ {
jv = {{kNameName_, record->name_}, jv = {{kNameName_, record->name_},
{kLatitudeName_, record->latitude_}, {kLatitudeName_, record->latitude_},
{kLongitudeName_, record->longitude_}}; {kLongitudeName_, record->longitude_}};
} }
friend PointOfInterest tag_invoke(boost::json::value_to_tag<PointOfInterest>, friend POIRecord tag_invoke(boost::json::value_to_tag<POIRecord>,
const boost::json::value& jv) const boost::json::value& jv)
{ {
return PointOfInterest( return POIRecord(
boost::json::value_to<std::string>(jv.at(kNameName_)), boost::json::value_to<std::string>(jv.at(kNameName_)),
boost::json::value_to<double>(jv.at(kLatitudeName_)), boost::json::value_to<double>(jv.at(kLatitudeName_)),
boost::json::value_to<double>(jv.at(kLongitudeName_))); boost::json::value_to<double>(jv.at(kLongitudeName_)));
} }
}; };
POIManager::POIManager() : p(std::make_unique<Impl>(this)) {}
void POIManager::Impl::InitializePOISettings()
{
std::string appDataPath {
QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)
.toStdString()};
if (!std::filesystem::exists(appDataPath))
{
if (!std::filesystem::create_directories(appDataPath))
{
logger_->error("Unable to create application data directory: \"{}\"",
appDataPath);
}
}
poiSettingsPath_ = appDataPath + "/points_of_interest.json";
}
void POIManager::Impl::ReadPOISettings() void POIManager::Impl::ReadPOISettings()
{ {
logger_->info("Reading point of intrest settings"); logger_->info("Reading point of interest settings");
boost::json::value poiJson = nullptr; boost::json::value poiJson = nullptr;
@ -84,16 +111,18 @@ void POIManager::Impl::ReadPOISettings()
{ {
// For each poi entry // For each poi entry
auto& poiArray = poiJson.as_array(); auto& poiArray = poiJson.as_array();
poiRecords_.reserve(poiArray.size());
for (auto& poiEntry : poiArray) for (auto& poiEntry : poiArray)
{ {
try try
{ {
PointOfInterest record = POIRecord record =
boost::json::value_to<PointOfInterest>(poiEntry); boost::json::value_to<POIRecord>(poiEntry);
if (!record.name_.empty()) if (!record.name_.empty())
{ {
// Add record poiRecords_.emplace_back(std::make_shared<POIRecord>(
record.name_, record.latitude_, record.longitude_));
} }
} }
catch (const std::exception& ex) catch (const std::exception& ex)
@ -101,9 +130,147 @@ void POIManager::Impl::ReadPOISettings()
logger_->warn("Invalid point of interest entry: {}", ex.what()); logger_->warn("Invalid point of interest entry: {}", ex.what());
} }
} }
logger_->debug("{} point of interest entries", poiRecords_.size());
} }
} }
void POIManager::Impl::WritePOISettings()
{
logger_->info("Saving point of interest settings");
auto poiJson = boost::json::value_from(poiRecords_);
util::json::WriteJsonFile(poiSettingsPath_, poiJson);
}
std::shared_ptr<POIManager::Impl::POIRecord>
POIManager::Impl::GetPOIByName(const std::string& name)
{
for (auto& poiRecord : poiRecords_)
{
if (poiRecord->name_ == name)
{
return poiRecord;
}
}
return nullptr;
}
POIManager::POIManager() : p(std::make_unique<Impl>(this))
{
// TODO THREADING?
try
{
p->InitializePOISettings();
// Read POI settings on startup
//main::Application::WaitForInitialization();
p->ReadPOISettings();
}
catch (const std::exception& ex)
{
logger_->error(ex.what());
}
}
POIManager::~POIManager()
{
p->WritePOISettings();
}
size_t POIManager::poi_count()
{
return p->poiRecords_.size();
}
// TODO deal with out of range/not found
types::PointOfInterest POIManager::get_poi(size_t index)
{
std::shared_ptr<POIManager::Impl::POIRecord> poiRecord =
p->poiRecords_[index];
return types::PointOfInterest(
poiRecord->name_, poiRecord->latitude_, poiRecord->longitude_);
}
types::PointOfInterest POIManager::get_poi(const std::string& name)
{
std::shared_ptr<POIManager::Impl::POIRecord> poiRecord =
p->GetPOIByName(name);
return types::PointOfInterest(
poiRecord->name_, poiRecord->latitude_, poiRecord->longitude_);
}
void POIManager::set_poi(size_t index, const types::PointOfInterest& poi)
{
std::shared_ptr<POIManager::Impl::POIRecord> poiRecord =
p->poiRecords_[index];
poiRecord->name_ = poi.name_;
poiRecord->latitude_ = poi.latitude_;
poiRecord->longitude_ = poi.longitude_;
}
void POIManager::set_poi(const std::string& name,
const types::PointOfInterest& poi)
{
std::shared_ptr<POIManager::Impl::POIRecord> poiRecord =
p->GetPOIByName(name);
poiRecord->name_ = poi.name_;
poiRecord->latitude_ = poi.latitude_;
poiRecord->longitude_ = poi.longitude_;
}
void POIManager::add_poi(const types::PointOfInterest& poi)
{
p->poiRecords_.emplace_back(std::make_shared<Impl::POIRecord>(
poi.name_, poi.latitude_, poi.longitude_));
}
void POIManager::move_poi(size_t from, size_t to)
{
if (from >= p->poiRecords_.size() || to >= p->poiRecords_.size())
{
return;
}
std::shared_ptr<POIManager::Impl::POIRecord> poiRecord =
p->poiRecords_[from];
if (from == to)
{
}
else if (from < to)
{
for (size_t i = from; i < to; i++)
{
p->poiRecords_[i] = p->poiRecords_[i + 1];
}
p->poiRecords_[to] = poiRecord;
}
else
{
for (size_t i = from; i > to; i--)
{
p->poiRecords_[i] = p->poiRecords_[i - 1];
}
p->poiRecords_[to] = poiRecord;
}
}
std::shared_ptr<POIManager> POIManager::Instance()
{
static std::weak_ptr<POIManager> poiManagerReference_ {};
std::shared_ptr<POIManager> poiManager = poiManagerReference_.lock();
if (poiManager == nullptr)
{
poiManager = std::make_shared<POIManager>();
poiManagerReference_ = poiManager;
}
return poiManager;
}
} // namespace manager } // namespace manager
} // namespace qt } // namespace qt
} // namespace scwx } // namespace scwx

View file

@ -2,6 +2,8 @@
#include <scwx/qt/types/poi_types.hpp> #include <scwx/qt/types/poi_types.hpp>
#include <string>
#include <QObject> #include <QObject>
namespace scwx namespace scwx
@ -19,6 +21,15 @@ public:
explicit POIManager(); explicit POIManager();
~POIManager(); ~POIManager();
size_t poi_count();
types::PointOfInterest get_poi(size_t index);
types::PointOfInterest get_poi(const std::string& name);
void set_poi(size_t index, const types::PointOfInterest& poi);
void set_poi(const std::string& name, const types::PointOfInterest& poi);
void add_poi(const types::PointOfInterest& poi);
void move_poi(size_t from, size_t to);
static std::shared_ptr<POIManager> Instance();
private: private:
class Impl; class Impl;