summaryrefslogtreecommitdiff
path: root/core/src/Model/GlobalStates.cpp
blob: 0c4e58ef4fccfb8b9c157da271ead2a9e663a763 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "GlobalStates.hpp"

#include "Model/Project.hpp"
#include "Utils/StandardDirectories.hpp"

#include <json/reader.h>
#include <json/value.h>
#include <json/writer.h>
#include <cassert>
#include <filesystem>
#include <fstream>
#include <memory>

namespace fs = std::filesystem;

static std::unique_ptr<GlobalStates> globalStateInstance;
static fs::path globalDataPath;

void GlobalStates::Init() {
	Init(StandardDirectories::UserData() / "cplt");
}

void GlobalStates::Init(std::filesystem::path userDataDir) {
	globalStateInstance = std::make_unique<GlobalStates>();
	globalDataPath = userDataDir;
	fs::create_directories(globalDataPath);

	// Reading recent projects
	[&]() {
		std::ifstream ifs(globalDataPath / "recents.json");
		if (!ifs) return;

		Json::Value root;
		ifs >> root;

		if (!root.isObject()) return;
		if (auto& recents = root["RecentProjects"]; recents.isArray()) {
			for (auto& elm : recents) {
				if (!elm.isString()) continue;

				fs::path path(elm.asCString());
				if (!fs::exists(path)) continue;

				auto utf8String = path.string();
				globalStateInstance->mRecentProjects.push_back(RecentProject{
					.path = std::move(path),
					.cachedUtf8String = std::move(utf8String),
				});
			}
		}
	}();
}

void GlobalStates::Shutdown() {
	if (!globalStateInstance) return;
	if (globalStateInstance->mDirty) {
		globalStateInstance->WriteToDisk();
	}
}

GlobalStates& GlobalStates::GetInstance() {
	return *globalStateInstance;
}

const std::filesystem::path& GlobalStates::GetUserDataPath() {
	return globalDataPath;
}

const std::vector<GlobalStates::RecentProject>& GlobalStates::GetRecentProjects() const {
	return mRecentProjects;
}

void GlobalStates::ClearRecentProjects() {
	mRecentProjects.clear();
	MarkDirty();
}

void GlobalStates::AddRecentProject(const Project& project) {
	mRecentProjects.push_back(RecentProject{
		.path = project.GetPath(),
		.cachedUtf8String = project.GetPath().string(),
	});
	MarkDirty();
}

void GlobalStates::MoveProjectToTop(const Project& project) {
	for (auto it = mRecentProjects.begin(); it != mRecentProjects.end(); ++it) {
		if (it->path == project.GetPath()) {
			std::rotate(it, it + 1, mRecentProjects.end());
			MarkDirty();
			return;
		}
	}
	AddRecentProject(project);
}

void GlobalStates::RemoveRecentProject(int idx) {
	assert(idx >= 0 && idx < mRecentProjects.size());

	mRecentProjects.erase(mRecentProjects.begin() + idx);
	MarkDirty();
}

void GlobalStates::WriteToDisk() const {
	Json::Value root;

	auto& recentProjects = root["RecentProjects"] = Json::Value(Json::arrayValue);
	for (auto& [path, _] : mRecentProjects) {
		recentProjects.append(Json::Value(path.string()));
	}

	std::ofstream ofs(globalDataPath / "recents.json");
	ofs << root;

	mDirty = false;
}

bool GlobalStates::IsDirty() const {
	return mDirty;
}

void GlobalStates::MarkDirty() {
	mDirty = true;
	OnModified();
}