6#include <nlohmann/json.hpp>
22 ssize_t len = readlink(
"/proc/self/exe", exe_path,
sizeof(exe_path) - 1);
27 size_t last_slash = exe_dir.find_last_of(
'/');
28 if (last_slash != String::npos) {
29 exe_dir = exe_dir.substr(0, last_slash);
32 config_file_ = exe_dir +
"/resources/projects/project_manager.json";
36 config_file_ =
"resources/projects/project_manager.json";
53 if (stat(resources_dir.c_str(), &st) != 0) {
54 if (mkdir(resources_dir.c_str(), 0755) != 0) {
55 LOG_ERROR(
"ProjectManager",
"Failed to create resources directory: " + resources_dir);
73 std::lock_guard<std::mutex> lock(
mutex_);
75 auto project = std::make_shared<BehaviorTreeProject>(name, description);
77 LOG_INFO(
"ProjectManager",
"Created new project: " + name);
82 std::lock_guard<std::mutex> lock(
mutex_);
85 std::ifstream file(filepath);
87 LOG_ERROR(
"ProjectManager",
"Project file not found: " + filepath);
93 auto project = std::make_shared<BehaviorTreeProject>();
94 if (!project->LoadFromFile(filepath)) {
95 LOG_ERROR(
"ProjectManager",
"Failed to load project from: " + filepath);
113 LOG_INFO(
"ProjectManager",
"Opened project: " + project->GetName() +
" from " + filepath);
118 std::lock_guard<std::mutex> lock(
mutex_);
121 LOG_ERROR(
"ProjectManager",
"No active project to save");
126 LOG_ERROR(
"ProjectManager",
"No project file path set");
141 std::lock_guard<std::mutex> lock(
mutex_);
144 LOG_ERROR(
"ProjectManager",
"No active project to save");
149 LOG_ERROR(
"ProjectManager",
"Failed to save project to: " + filepath);
160 LOG_INFO(
"ProjectManager",
"Saved project as: " + filepath);
165 std::lock_guard<std::mutex> lock(
mutex_);
168 LOG_WARNING(
"ProjectManager",
"No active project to close");
177 LOG_INFO(
"ProjectManager",
"Closed project: " + name);
182 std::lock_guard<std::mutex> lock(
mutex_);
187 std::lock_guard<std::mutex> lock(
mutex_);
192 std::lock_guard<std::mutex> lock(
mutex_);
197 std::lock_guard<std::mutex> lock(
mutex_);
202 std::lock_guard<std::mutex> lock(
mutex_);
213 std::lock_guard<std::mutex> lock(
mutex_);
232 std::lock_guard<std::mutex> lock(
mutex_);
245 std::lock_guard<std::mutex> lock(
mutex_);
251 std::ifstream file(filepath);
256 std::lock_guard<std::mutex> lock(
mutex_);
258 LOG_INFO(
"ProjectManager",
"Resetting to defaults");
271 if (!file.is_open()) {
281 if (json.contains(
"recent_projects")) {
285 std::vector<String> valid_projects;
288 valid_projects.push_back(project);
290 LOG_WARNING(
"ProjectManager",
"Recent project no longer exists: " + project);
297 "Loaded config with " + std::to_string(
recent_projects_.size()) +
" recent project(s)");
299 }
catch (
const std::exception &e) {
300 LOG_ERROR(
"ProjectManager",
"Failed to load config file: " +
String(e.what()));
313 json[
"version"] =
"1.0";
316 if (!file.is_open()) {
321 file << std::setw(4) << json << std::endl;
326 }
catch (
const std::exception &e) {
327 LOG_ERROR(
"ProjectManager",
"Failed to save config file: " +
String(e.what()));
#define LOG_ERROR(category, message)
#define LOG_WARNING(category, message)
#define LOG_INFO(category, message)
void AddToRecentProjectsInternal(const String &filepath)
void AddToRecentProjects(const String &filepath)
void RemoveFromRecentProjectsInternal(const String &filepath)
static const size_t MAX_RECENT_PROJECTS
String projects_directory_
bool RecentProjectExists(const String &filepath) const
bool SaveProjectAs(const String &filepath)
bool EnsureProjectsDirectoryExists()
bool OpenProject(const String &filepath)
bool HasActiveProject() const
bool IsProjectModified() const
void SetProjectModified(bool modified)
static ProjectManager & GetInstance()
void RemoveFromRecentProjects(const String &filepath)
const std::vector< String > & GetRecentProjects() const
std::vector< String > recent_projects_
std::shared_ptr< BehaviorTreeProject > active_project_
void ClearRecentProjects()
ProjectManager(const ProjectManager &)=delete
String GetActiveProjectPath() const
std::shared_ptr< BehaviorTreeProject > GetActiveProject() const
String active_project_path_
std::shared_ptr< BehaviorTreeProject > CreateProject(const String &name, const String &description="")
Main types header for EmberCore.
std::string String
Framework-agnostic string type.