2023-12-11 15:54:22 +01:00
|
|
|
#include <hex/api/workspace_manager.hpp>
|
|
|
|
#include <hex/api/layout_manager.hpp>
|
|
|
|
|
|
|
|
#include <hex/helpers/logger.hpp>
|
2024-01-30 15:50:00 +01:00
|
|
|
#include <hex/helpers/auto_reset.hpp>
|
2023-12-11 15:54:22 +01:00
|
|
|
|
|
|
|
#include <wolv/io/file.hpp>
|
|
|
|
|
|
|
|
#include <nlohmann/json.hpp>
|
2023-12-12 00:16:21 +01:00
|
|
|
|
|
|
|
#include <imgui.h>
|
2024-02-28 22:10:48 +01:00
|
|
|
#include <wolv/utils/string.hpp>
|
2023-12-11 15:54:22 +01:00
|
|
|
|
|
|
|
namespace hex {
|
|
|
|
|
2024-01-30 11:21:34 +01:00
|
|
|
AutoReset<std::map<std::string, WorkspaceManager::Workspace>> WorkspaceManager::s_workspaces;
|
|
|
|
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_currentWorkspace = s_workspaces->end();
|
|
|
|
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_previousWorkspace = s_workspaces->end();
|
2024-02-28 22:10:48 +01:00
|
|
|
decltype(WorkspaceManager::s_workspaces)::Type::iterator WorkspaceManager::s_workspaceToRemove = s_workspaces->end();
|
2023-12-11 15:54:22 +01:00
|
|
|
|
|
|
|
void WorkspaceManager::createWorkspace(const std::string& name, const std::string &layout) {
|
2024-01-30 11:21:34 +01:00
|
|
|
s_currentWorkspace = s_workspaces->insert_or_assign(name, Workspace {
|
2024-02-28 22:10:48 +01:00
|
|
|
.layout = layout.empty() ? LayoutManager::saveToString() : layout,
|
|
|
|
.path = {},
|
|
|
|
.builtin = false
|
2024-01-29 20:50:00 +01:00
|
|
|
}).first;
|
2023-12-11 15:54:22 +01:00
|
|
|
|
2024-02-28 22:10:48 +01:00
|
|
|
for (const auto &workspaceFolder : fs::getDefaultPaths(fs::ImHexPath::Workspaces)) {
|
|
|
|
const auto workspacePath = workspaceFolder / (name + ".hexws");
|
|
|
|
if (exportToFile(workspacePath)) {
|
|
|
|
s_currentWorkspace->second.path = workspacePath;
|
2023-12-11 15:54:22 +01:00
|
|
|
break;
|
2024-02-28 22:10:48 +01:00
|
|
|
}
|
2023-12-11 15:54:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WorkspaceManager::switchWorkspace(const std::string& name) {
|
2024-01-30 11:21:34 +01:00
|
|
|
const auto newWorkspace = s_workspaces->find(name);
|
|
|
|
if (newWorkspace != s_workspaces->end()) {
|
2023-12-12 00:16:21 +01:00
|
|
|
s_currentWorkspace = newWorkspace;
|
|
|
|
log::info("Switching to workspace '{}'", name);
|
2023-12-11 15:54:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WorkspaceManager::importFromFile(const std::fs::path& path) {
|
2024-02-28 22:10:48 +01:00
|
|
|
if (std::ranges::any_of(*s_workspaces, [path](const auto &pair) { return pair.second.path == path; }))
|
|
|
|
return;
|
|
|
|
|
2023-12-11 15:54:22 +01:00
|
|
|
wolv::io::File file(path, wolv::io::File::Mode::Read);
|
|
|
|
if (!file.isValid()) {
|
|
|
|
log::error("Failed to load workspace from file '{}'", path.string());
|
2024-02-19 22:22:59 +01:00
|
|
|
file.remove();
|
2023-12-11 15:54:22 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto content = file.readString();
|
|
|
|
try {
|
|
|
|
auto json = nlohmann::json::parse(content.begin(), content.end());
|
|
|
|
|
2024-01-30 11:21:34 +01:00
|
|
|
const std::string name = json["name"];
|
2023-12-11 15:54:22 +01:00
|
|
|
std::string layout = json["layout"];
|
2024-02-28 22:10:48 +01:00
|
|
|
const bool builtin = json.value("builtin", false);
|
2023-12-11 15:54:22 +01:00
|
|
|
|
2024-01-30 11:21:34 +01:00
|
|
|
(*s_workspaces)[name] = Workspace {
|
2023-12-11 15:54:22 +01:00
|
|
|
.layout = std::move(layout),
|
2024-02-28 22:10:48 +01:00
|
|
|
.path = path,
|
|
|
|
.builtin = builtin
|
2023-12-11 15:54:22 +01:00
|
|
|
};
|
|
|
|
} catch (nlohmann::json::exception &e) {
|
|
|
|
log::error("Failed to load workspace from file '{}': {}", path.string(), e.what());
|
2024-02-19 22:22:59 +01:00
|
|
|
file.remove();
|
2023-12-11 15:54:22 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-28 22:10:48 +01:00
|
|
|
bool WorkspaceManager::exportToFile(std::fs::path path, std::string workspaceName, bool builtin) {
|
2023-12-11 15:54:22 +01:00
|
|
|
if (path.empty()) {
|
2024-01-30 11:21:34 +01:00
|
|
|
if (s_currentWorkspace == s_workspaces->end())
|
2023-12-11 15:54:22 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
path = s_currentWorkspace->second.path;
|
|
|
|
}
|
|
|
|
|
2023-12-14 09:36:29 +01:00
|
|
|
if (workspaceName.empty())
|
|
|
|
workspaceName = s_currentWorkspace->first;
|
|
|
|
|
2023-12-11 15:54:22 +01:00
|
|
|
wolv::io::File file(path, wolv::io::File::Mode::Create);
|
|
|
|
|
|
|
|
if (!file.isValid())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
nlohmann::json json;
|
2023-12-14 09:36:29 +01:00
|
|
|
json["name"] = workspaceName;
|
|
|
|
json["layout"] = LayoutManager::saveToString();
|
2024-02-28 22:10:48 +01:00
|
|
|
json["builtin"] = builtin;
|
2023-12-11 15:54:22 +01:00
|
|
|
|
|
|
|
file.writeString(json.dump(4));
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2024-02-28 22:10:48 +01:00
|
|
|
void WorkspaceManager::removeWorkspace(const std::string& name) {
|
|
|
|
for (const auto &[workspaceName, workspace] : *s_workspaces) {
|
|
|
|
if (workspaceName == name) {
|
|
|
|
log::info("{}", wolv::util::toUTF8String(workspace.path));
|
|
|
|
if (wolv::io::File(workspace.path, wolv::io::File::Mode::Write).remove()) {
|
|
|
|
log::info("Removed workspace '{}'", name);
|
|
|
|
|
|
|
|
switchWorkspace(s_workspaces->begin()->first);
|
|
|
|
s_workspaces->erase(workspaceName);
|
|
|
|
} else {
|
|
|
|
log::error("Failed to remove workspace '{}'", name);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-11 15:54:22 +01:00
|
|
|
|
2023-12-12 00:16:21 +01:00
|
|
|
void WorkspaceManager::process() {
|
|
|
|
if (s_previousWorkspace != s_currentWorkspace) {
|
2024-02-28 22:10:48 +01:00
|
|
|
log::info("Updating workspace");
|
2024-01-30 11:21:34 +01:00
|
|
|
if (s_previousWorkspace != s_workspaces->end())
|
2024-02-28 22:10:48 +01:00
|
|
|
exportToFile(s_previousWorkspace->second.path, s_previousWorkspace->first, s_previousWorkspace->second.builtin);
|
2023-12-12 00:16:21 +01:00
|
|
|
|
2023-12-24 14:51:47 +01:00
|
|
|
LayoutManager::closeAllViews();
|
2023-12-12 00:16:21 +01:00
|
|
|
ImGui::LoadIniSettingsFromMemory(s_currentWorkspace->second.layout.c_str());
|
|
|
|
|
|
|
|
s_previousWorkspace = s_currentWorkspace;
|
2024-02-28 22:10:48 +01:00
|
|
|
|
|
|
|
if (s_workspaceToRemove != s_workspaces->end()) {
|
|
|
|
s_workspaces->erase(s_workspaceToRemove);
|
|
|
|
s_workspaceToRemove = s_workspaces->end();
|
|
|
|
}
|
2023-12-12 00:16:21 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-12-11 15:54:22 +01:00
|
|
|
void WorkspaceManager::reset() {
|
2024-01-30 11:21:34 +01:00
|
|
|
s_workspaces->clear();
|
|
|
|
s_currentWorkspace = s_workspaces->end();
|
|
|
|
s_previousWorkspace = s_workspaces->end();
|
2023-12-11 15:54:22 +01:00
|
|
|
}
|
|
|
|
|
2024-02-28 22:10:48 +01:00
|
|
|
void WorkspaceManager::reload() {
|
|
|
|
WorkspaceManager::reset();
|
|
|
|
|
|
|
|
for (const auto &defaultPath : fs::getDefaultPaths(fs::ImHexPath::Workspaces)) {
|
|
|
|
for (const auto &entry : std::fs::directory_iterator(defaultPath)) {
|
|
|
|
if (!entry.is_regular_file())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
const auto &path = entry.path();
|
|
|
|
if (path.extension() != ".hexws")
|
|
|
|
continue;
|
|
|
|
|
|
|
|
WorkspaceManager::importFromFile(path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-12-11 15:54:22 +01:00
|
|
|
|
|
|
|
|
|
|
|
}
|