mirror of https://github.com/WerWolv/ImHex
impr: Add auto backups to crash restore popup
This commit is contained in:
parent
95ff52b025
commit
2c7da65242
|
|
@ -5,6 +5,7 @@
|
|||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <wolv/io/fs.hpp>
|
||||
#include <hex/ui/popup.hpp>
|
||||
|
||||
namespace hex::plugin::builtin::recent {
|
||||
|
||||
|
|
@ -53,6 +54,31 @@ namespace hex::plugin::builtin::recent {
|
|||
|
||||
};
|
||||
|
||||
class PopupAutoBackups : public Popup<PopupAutoBackups> {
|
||||
private:
|
||||
struct BackupEntry {
|
||||
std::string displayName;
|
||||
std::fs::path path;
|
||||
std::tm time;
|
||||
|
||||
bool operator<(const BackupEntry& other) const {
|
||||
auto a = this->time;
|
||||
auto b = other.time;
|
||||
return std::mktime(&a) < std::mktime(&b);
|
||||
}
|
||||
};
|
||||
public:
|
||||
PopupAutoBackups();
|
||||
|
||||
void drawContent() override;
|
||||
[[nodiscard]] ImGuiWindowFlags getFlags() const override;
|
||||
|
||||
static std::vector<BackupEntry> getAutoBackups();
|
||||
|
||||
private:
|
||||
std::vector<BackupEntry> m_backups;
|
||||
};
|
||||
|
||||
void registerEventHandlers();
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -170,12 +170,12 @@ namespace hex::plugin::builtin {
|
|||
|
||||
// Request, as this puts us into a project state
|
||||
RequestUpdateWindowTitle::post();
|
||||
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.save_project.name");
|
||||
|
||||
EventProjectSaved::post();
|
||||
}
|
||||
|
||||
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.save_project.name");
|
||||
|
||||
EventProjectSaved::post();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include <content/recent.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
|
||||
|
|
@ -17,7 +19,6 @@
|
|||
#include <wolv/utils/guards.hpp>
|
||||
#include <wolv/utils/string.hpp>
|
||||
|
||||
#include <content/recent.hpp>
|
||||
#include <toasts/toast_notification.hpp>
|
||||
#include <fonts/vscode_icons.hpp>
|
||||
|
||||
|
|
@ -36,55 +37,68 @@ namespace hex::plugin::builtin::recent {
|
|||
std::list<RecentEntry> s_recentEntries;
|
||||
std::atomic_bool s_autoBackupsFound = false;
|
||||
|
||||
}
|
||||
|
||||
class PopupAutoBackups : public Popup<PopupAutoBackups> {
|
||||
private:
|
||||
struct BackupEntry {
|
||||
std::string displayName;
|
||||
std::fs::path path;
|
||||
};
|
||||
public:
|
||||
PopupAutoBackups() : Popup("hex.builtin.welcome.start.recent.auto_backups", true, true) {
|
||||
for (const auto &backupPath : paths::Backups.read()) {
|
||||
for (const auto &entry : std::fs::directory_iterator(backupPath)) {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".hexproj") {
|
||||
wolv::io::File backupFile(entry.path(), wolv::io::File::Mode::Read);
|
||||
std::vector<PopupAutoBackups::BackupEntry> PopupAutoBackups::getAutoBackups() {
|
||||
std::set<BackupEntry> result;
|
||||
|
||||
m_backups.emplace_back(
|
||||
fmt::format("hex.builtin.welcome.start.recent.auto_backups.backup"_lang, fmt::gmtime(backupFile.getFileInfo()->st_ctime)),
|
||||
entry.path()
|
||||
);
|
||||
}
|
||||
}
|
||||
for (const auto &backupPath : paths::Backups.read()) {
|
||||
for (const auto &entry : std::fs::directory_iterator(backupPath)) {
|
||||
if (entry.is_regular_file() && entry.path().extension() == ".hexproj") {
|
||||
// auto_backup.{:%y%m%d_%H%M%S}.hexproj
|
||||
auto fileName = wolv::util::toUTF8String(entry.path().stem());
|
||||
if (!fileName.starts_with("auto_backup."))
|
||||
continue;
|
||||
|
||||
wolv::io::File backupFile(entry.path(), wolv::io::File::Mode::Read);
|
||||
|
||||
auto creationTimeString = fileName.substr(12);
|
||||
|
||||
std::chrono::sys_seconds utcSeconds;
|
||||
std::istringstream ss(creationTimeString);
|
||||
ss >> std::chrono::parse("%y%m%d_%H%M%S", utcSeconds);
|
||||
if (ss.fail())
|
||||
continue;
|
||||
|
||||
auto utcTime = std::chrono::system_clock::to_time_t(utcSeconds);
|
||||
std::tm localTm = *std::localtime(&utcTime);
|
||||
|
||||
result.emplace(
|
||||
fmt::format("hex.builtin.welcome.start.recent.auto_backups.backup"_lang, localTm),
|
||||
entry.path(),
|
||||
localTm
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { result.begin(), result.end() };
|
||||
}
|
||||
|
||||
PopupAutoBackups::PopupAutoBackups() : Popup("hex.builtin.welcome.start.recent.auto_backups", true, true) {
|
||||
m_backups = getAutoBackups();
|
||||
}
|
||||
|
||||
void PopupAutoBackups::drawContent() {
|
||||
if (ImGui::BeginTable("AutoBackups", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV, ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 5))) {
|
||||
for (const auto &backup : m_backups | std::views::reverse | std::views::take(10)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Selectable(backup.displayName.c_str())) {
|
||||
ProjectFile::load(backup.path);
|
||||
Popup::close();
|
||||
}
|
||||
}
|
||||
|
||||
void drawContent() override {
|
||||
if (ImGui::BeginTable("AutoBackups", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV, ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 5))) {
|
||||
for (const auto &backup : m_backups | std::views::reverse | std::views::take(10)) {
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
if (ImGui::Selectable(backup.displayName.c_str())) {
|
||||
ProjectFile::load(backup.path);
|
||||
Popup::close();
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
|
||||
this->close();
|
||||
}
|
||||
|
||||
[[nodiscard]] ImGuiWindowFlags getFlags() const override {
|
||||
return ImGuiWindowFlags_AlwaysAutoResize;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<BackupEntry> m_backups;
|
||||
};
|
||||
if (ImGui::IsKeyPressed(ImGuiKey_Escape))
|
||||
this->close();
|
||||
}
|
||||
|
||||
[[nodiscard]] ImGuiWindowFlags PopupAutoBackups::getFlags() const {
|
||||
return ImGuiWindowFlags_AlwaysAutoResize;
|
||||
}
|
||||
|
||||
void saveCurrentProjectAsRecent() {
|
||||
|
|
|
|||
|
|
@ -56,13 +56,15 @@ namespace hex::plugin::builtin {
|
|||
class PopupRestoreBackup : public Popup<PopupRestoreBackup> {
|
||||
private:
|
||||
std::fs::path m_logFilePath;
|
||||
bool m_hasAutoBackups;
|
||||
std::function<void()> m_restoreCallback;
|
||||
std::function<void()> m_deleteCallback;
|
||||
bool m_reportError = true;
|
||||
public:
|
||||
PopupRestoreBackup(std::fs::path logFilePath, const std::function<void()> &restoreCallback, const std::function<void()> &deleteCallback)
|
||||
PopupRestoreBackup(std::fs::path logFilePath, bool hasAutoBackups, const std::function<void()> &restoreCallback, const std::function<void()> &deleteCallback)
|
||||
: Popup("hex.builtin.popup.safety_backup.title"),
|
||||
m_logFilePath(std::move(logFilePath)),
|
||||
m_hasAutoBackups(hasAutoBackups),
|
||||
m_restoreCallback(restoreCallback),
|
||||
m_deleteCallback(deleteCallback) {
|
||||
|
||||
|
|
@ -123,6 +125,12 @@ namespace hex::plugin::builtin {
|
|||
|
||||
this->close();
|
||||
}
|
||||
|
||||
if (m_hasAutoBackups) {
|
||||
if (ImGui::Button("Show Automatic Backups", ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
|
||||
recent::PopupAutoBackups::open();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -739,6 +747,10 @@ namespace hex::plugin::builtin {
|
|||
auto backupFilePathOld = path / BackupFileName;
|
||||
backupFilePathOld.replace_extension(".hexproj.old");
|
||||
|
||||
bool autoBackupsEnabled = ContentRegistry::Settings::read<int>("hex.builtin.setting.general", "hex.builtin.setting.general.auto_backup_time", 0) > 0;
|
||||
auto autoBackups = recent::PopupAutoBackups::getAutoBackups();
|
||||
bool hasAutoBackups = autoBackupsEnabled && !autoBackups.empty();
|
||||
|
||||
bool hasBackupFile = wolv::io::fs::exists(backupFilePath);
|
||||
|
||||
if (!hasProject && !hasBackupFile) {
|
||||
|
|
@ -762,13 +774,16 @@ namespace hex::plugin::builtin {
|
|||
PopupRestoreBackup::open(
|
||||
// Path of log file
|
||||
crashFileData.value("logFile", ""),
|
||||
hasAutoBackups,
|
||||
|
||||
// Restore callback
|
||||
[crashFileData, backupFilePath, hasProject, hasBackupFile] {
|
||||
[crashFileData, backupFilePath, hasProject, hasBackupFile, hasAutoBackups, autoBackups = std::move(autoBackups)] {
|
||||
if (hasBackupFile) {
|
||||
if (ProjectFile::load(backupFilePath)) {
|
||||
if (hasProject) {
|
||||
ProjectFile::setPath(crashFileData["project"].get<std::string>());
|
||||
} else if (hasAutoBackups) {
|
||||
ProjectFile::setPath(autoBackups.front().path);
|
||||
} else {
|
||||
ProjectFile::setPath("");
|
||||
}
|
||||
|
|
@ -779,6 +794,8 @@ namespace hex::plugin::builtin {
|
|||
} else {
|
||||
if (hasProject) {
|
||||
ProjectFile::setPath(crashFileData["project"].get<std::string>());
|
||||
} else if (hasAutoBackups) {
|
||||
ProjectFile::setPath(autoBackups.front().path);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in New Issue