feat: Added automatic backups
This commit is contained in:
parent
e6796d1458
commit
7a4358a5ec
@ -38,6 +38,7 @@ namespace hex::fs {
|
|||||||
Plugins,
|
Plugins,
|
||||||
Yara,
|
Yara,
|
||||||
Config,
|
Config,
|
||||||
|
Backups,
|
||||||
Resources,
|
Resources,
|
||||||
Constants,
|
Constants,
|
||||||
Encodings,
|
Encodings,
|
||||||
|
@ -375,6 +375,9 @@ namespace hex::fs {
|
|||||||
case ImHexPath::Config:
|
case ImHexPath::Config:
|
||||||
result = appendPath(getConfigPaths(), "config");
|
result = appendPath(getConfigPaths(), "config");
|
||||||
break;
|
break;
|
||||||
|
case ImHexPath::Backups:
|
||||||
|
result = appendPath(getDataPaths(), "backups");
|
||||||
|
break;
|
||||||
case ImHexPath::Encodings:
|
case ImHexPath::Encodings:
|
||||||
result = appendPath(getDataPaths(), "encodings");
|
result = appendPath(getDataPaths(), "encodings");
|
||||||
break;
|
break;
|
||||||
|
@ -40,6 +40,9 @@ namespace ImGuiExt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Texture::Texture(const ImU8 *buffer, int size, Filter filter, int width, int height) {
|
Texture::Texture(const ImU8 *buffer, int size, Filter filter, int width, int height) {
|
||||||
|
if (size == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
unsigned char *imageData = stbi_load_from_memory(buffer, size, &this->m_width, &this->m_height, nullptr, 4);
|
unsigned char *imageData = stbi_load_from_memory(buffer, size, &this->m_width, &this->m_height, nullptr, 4);
|
||||||
if (imageData == nullptr) {
|
if (imageData == nullptr) {
|
||||||
if (width * height * 4 > size)
|
if (width * height * 4 > size)
|
||||||
|
@ -53,6 +53,7 @@ namespace hex {
|
|||||||
|
|
||||||
std::string m_windowTitle;
|
std::string m_windowTitle;
|
||||||
|
|
||||||
|
double m_lastStartFrameTime = 0;
|
||||||
double m_lastFrameTime = 0;
|
double m_lastFrameTime = 0;
|
||||||
|
|
||||||
ImGuiExt::Texture m_logoTexture;
|
ImGuiExt::Texture m_logoTexture;
|
||||||
|
@ -158,7 +158,7 @@ namespace hex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Window::fullFrame() {
|
void Window::fullFrame() {
|
||||||
this->m_lastFrameTime = glfwGetTime();
|
this->m_lastStartFrameTime = glfwGetTime();
|
||||||
|
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
@ -171,7 +171,7 @@ namespace hex {
|
|||||||
void Window::loop() {
|
void Window::loop() {
|
||||||
u64 frameCount = 0;
|
u64 frameCount = 0;
|
||||||
while (!glfwWindowShouldClose(this->m_window)) {
|
while (!glfwWindowShouldClose(this->m_window)) {
|
||||||
this->m_lastFrameTime = glfwGetTime();
|
this->m_lastStartFrameTime = glfwGetTime();
|
||||||
|
|
||||||
if (!glfwGetWindowAttrib(this->m_window, GLFW_VISIBLE) || glfwGetWindowAttrib(this->m_window, GLFW_ICONIFIED)) {
|
if (!glfwGetWindowAttrib(this->m_window, GLFW_VISIBLE) || glfwGetWindowAttrib(this->m_window, GLFW_ICONIFIED)) {
|
||||||
// If the application is minimized or not visible, don't render anything
|
// If the application is minimized or not visible, don't render anything
|
||||||
@ -189,10 +189,10 @@ namespace hex {
|
|||||||
frameCount < 100;
|
frameCount < 100;
|
||||||
|
|
||||||
// Calculate the time until the next frame
|
// Calculate the time until the next frame
|
||||||
const double timeout = std::max(0.0, (1.0 / 5.0) - (glfwGetTime() - this->m_lastFrameTime));
|
const double timeout = std::max(0.0, (1.0 / 5.0) - (glfwGetTime() - this->m_lastStartFrameTime));
|
||||||
|
|
||||||
// If the frame rate has been unlocked for 5 seconds, lock it again
|
// If the frame rate has been unlocked for 5 seconds, lock it again
|
||||||
if ((this->m_lastFrameTime - this->m_frameRateUnlockTime) > 5 && this->m_frameRateTemporarilyUnlocked && !frameRateUnlocked) {
|
if ((this->m_lastStartFrameTime - this->m_frameRateUnlockTime) > 5 && this->m_frameRateTemporarilyUnlocked && !frameRateUnlocked) {
|
||||||
this->m_frameRateTemporarilyUnlocked = false;
|
this->m_frameRateTemporarilyUnlocked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ namespace hex {
|
|||||||
if (frameRateUnlocked || this->m_frameRateTemporarilyUnlocked) {
|
if (frameRateUnlocked || this->m_frameRateTemporarilyUnlocked) {
|
||||||
if (!this->m_frameRateTemporarilyUnlocked) {
|
if (!this->m_frameRateTemporarilyUnlocked) {
|
||||||
this->m_frameRateTemporarilyUnlocked = true;
|
this->m_frameRateTemporarilyUnlocked = true;
|
||||||
this->m_frameRateUnlockTime = this->m_lastFrameTime;
|
this->m_frameRateUnlockTime = this->m_lastStartFrameTime;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
glfwWaitEventsTimeout(timeout);
|
glfwWaitEventsTimeout(timeout);
|
||||||
@ -222,12 +222,14 @@ namespace hex {
|
|||||||
glfwSwapInterval(0);
|
glfwSwapInterval(0);
|
||||||
} else {
|
} else {
|
||||||
glfwSwapInterval(0);
|
glfwSwapInterval(0);
|
||||||
const auto frameTime = glfwGetTime() - this->m_lastFrameTime;
|
const auto frameTime = glfwGetTime() - this->m_lastStartFrameTime;
|
||||||
const auto targetFrameTime = 1.0 / targetFPS;
|
const auto targetFrameTime = 1.0 / targetFPS;
|
||||||
if (frameTime < targetFrameTime) {
|
if (frameTime < targetFrameTime) {
|
||||||
glfwWaitEventsTimeout(targetFrameTime - frameTime);
|
glfwWaitEventsTimeout(targetFrameTime - frameTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->m_lastFrameTime = glfwGetTime() - this->m_lastStartFrameTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,10 +667,10 @@ namespace hex {
|
|||||||
if (auto &popups = impl::PopupBase::getOpenPopups(); !popups.empty()) {
|
if (auto &popups = impl::PopupBase::getOpenPopups(); !popups.empty()) {
|
||||||
if (!ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId)) {
|
if (!ImGui::IsPopupOpen(ImGuiID(0), ImGuiPopupFlags_AnyPopupId)) {
|
||||||
if (popupDelay <= -1.0) {
|
if (popupDelay <= -1.0) {
|
||||||
popupDelay = 200;
|
popupDelay = 0.2;
|
||||||
} else {
|
} else {
|
||||||
popupDelay -= this->m_lastFrameTime;
|
popupDelay -= this->m_lastFrameTime;
|
||||||
if (popupDelay < 0) {
|
if (popupDelay < 0 || popups.size() == 1) {
|
||||||
popupDelay = -2.0;
|
popupDelay = -2.0;
|
||||||
currPopup = std::move(popups.back());
|
currPopup = std::move(popups.back());
|
||||||
name = Lang(currPopup->getUnlocalizedName());
|
name = Lang(currPopup->getUnlocalizedName());
|
||||||
|
@ -118,6 +118,9 @@
|
|||||||
"hex.builtin.common.offset": "Offset",
|
"hex.builtin.common.offset": "Offset",
|
||||||
"hex.builtin.common.okay": "Okay",
|
"hex.builtin.common.okay": "Okay",
|
||||||
"hex.builtin.common.open": "Open",
|
"hex.builtin.common.open": "Open",
|
||||||
|
"hex.builtin.common.on": "On",
|
||||||
|
"hex.builtin.common.off": "Off",
|
||||||
|
"hex.builtin.common.path": "Path",
|
||||||
"hex.builtin.common.percentage": "Percentage",
|
"hex.builtin.common.percentage": "Percentage",
|
||||||
"hex.builtin.common.processing": "Processing",
|
"hex.builtin.common.processing": "Processing",
|
||||||
"hex.builtin.common.project": "Project",
|
"hex.builtin.common.project": "Project",
|
||||||
@ -573,14 +576,17 @@
|
|||||||
"hex.builtin.setting.general": "General",
|
"hex.builtin.setting.general": "General",
|
||||||
"hex.builtin.setting.general.patterns": "Patterns",
|
"hex.builtin.setting.general.patterns": "Patterns",
|
||||||
"hex.builtin.setting.general.network": "Network",
|
"hex.builtin.setting.general.network": "Network",
|
||||||
|
"hex.builtin.setting.general.auto_backup_time": "Periodically backup project",
|
||||||
|
"hex.builtin.setting.general.auto_backup_time.format.simple": "Every {0}s",
|
||||||
|
"hex.builtin.setting.general.auto_backup_time.format.extended": "Every {0}m {1}s",
|
||||||
"hex.builtin.setting.general.auto_load_patterns": "Auto-load supported pattern",
|
"hex.builtin.setting.general.auto_load_patterns": "Auto-load supported pattern",
|
||||||
"hex.builtin.setting.general.server_contact": "Enable update checks and usage statistics",
|
"hex.builtin.setting.general.server_contact": "Enable update checks and usage statistics",
|
||||||
"hex.builtin.setting.font.load_all_unicode_chars": "Load all unicode characters",
|
|
||||||
"hex.builtin.setting.general.network_interface": "Enable network interface",
|
"hex.builtin.setting.general.network_interface": "Enable network interface",
|
||||||
"hex.builtin.setting.general.save_recent_providers": "Save recently used providers",
|
"hex.builtin.setting.general.save_recent_providers": "Save recently used providers",
|
||||||
"hex.builtin.setting.general.show_tips": "Show tips on startup",
|
"hex.builtin.setting.general.show_tips": "Show tips on startup",
|
||||||
"hex.builtin.setting.general.sync_pattern_source": "Sync pattern source code between providers",
|
"hex.builtin.setting.general.sync_pattern_source": "Sync pattern source code between providers",
|
||||||
"hex.builtin.setting.general.upload_crash_logs": "Upload crash reports",
|
"hex.builtin.setting.general.upload_crash_logs": "Upload crash reports",
|
||||||
|
"hex.builtin.setting.font.load_all_unicode_chars": "Load all unicode characters",
|
||||||
"hex.builtin.setting.hex_editor": "Hex Editor",
|
"hex.builtin.setting.hex_editor": "Hex Editor",
|
||||||
"hex.builtin.setting.hex_editor.byte_padding": "Extra byte cell padding",
|
"hex.builtin.setting.hex_editor.byte_padding": "Extra byte cell padding",
|
||||||
"hex.builtin.setting.hex_editor.bytes_per_row": "Bytes per row",
|
"hex.builtin.setting.hex_editor.bytes_per_row": "Bytes per row",
|
||||||
@ -1174,6 +1180,8 @@
|
|||||||
"hex.builtin.welcome.start.open_other": "Other Providers",
|
"hex.builtin.welcome.start.open_other": "Other Providers",
|
||||||
"hex.builtin.welcome.start.open_project": "Open Project",
|
"hex.builtin.welcome.start.open_project": "Open Project",
|
||||||
"hex.builtin.welcome.start.recent": "Recent Files",
|
"hex.builtin.welcome.start.recent": "Recent Files",
|
||||||
|
"hex.builtin.welcome.start.recent.auto_backups": "Auto Backups",
|
||||||
|
"hex.builtin.welcome.start.recent.auto_backups.backup": "Backup from {:%Y-%m-%d %H:%M:%S}",
|
||||||
"hex.builtin.welcome.tip_of_the_day": "Tip of the Day",
|
"hex.builtin.welcome.tip_of_the_day": "Tip of the Day",
|
||||||
"hex.builtin.welcome.update.desc": "ImHex {0} just released! Download it here.",
|
"hex.builtin.welcome.update.desc": "ImHex {0} just released! Download it here.",
|
||||||
"hex.builtin.welcome.update.link": "https://github.com/WerWolv/ImHex/releases/latest",
|
"hex.builtin.welcome.update.link": "https://github.com/WerWolv/ImHex/releases/latest",
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
#include <hex/api/content_registry.hpp>
|
#include <hex/api/content_registry.hpp>
|
||||||
#include <hex/api/localization_manager.hpp>
|
#include <hex/api/localization_manager.hpp>
|
||||||
#include <hex/api/event_manager.hpp>
|
#include <hex/api/event_manager.hpp>
|
||||||
|
#include <hex/api/project_file_manager.hpp>
|
||||||
|
|
||||||
#include <wolv/utils/guards.hpp>
|
#include <wolv/utils/guards.hpp>
|
||||||
#include <wolv/net/socket_server.hpp>
|
#include <wolv/net/socket_server.hpp>
|
||||||
|
|
||||||
|
#include <hex/helpers/fmt.hpp>
|
||||||
|
#include <fmt/chrono.h>
|
||||||
#include <hex/helpers/logger.hpp>
|
#include <hex/helpers/logger.hpp>
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
@ -12,6 +15,7 @@
|
|||||||
namespace hex::plugin::builtin {
|
namespace hex::plugin::builtin {
|
||||||
|
|
||||||
static bool networkInterfaceServiceEnabled = false;
|
static bool networkInterfaceServiceEnabled = false;
|
||||||
|
static int autoBackupTime = 0;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -58,14 +62,37 @@ namespace hex::plugin::builtin {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void handleAutoBackup() {
|
||||||
|
auto now = std::chrono::steady_clock::now();
|
||||||
|
static std::chrono::time_point<std::chrono::steady_clock> lastBackupTime = now;
|
||||||
|
|
||||||
|
if (autoBackupTime > 0 && (now - lastBackupTime) > std::chrono::seconds(autoBackupTime)) {
|
||||||
|
lastBackupTime = now;
|
||||||
|
|
||||||
|
if (ImHexApi::Provider::isValid()) {
|
||||||
|
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Backups)) {
|
||||||
|
const auto fileName = hex::format("auto_backup.{:%y%m%d_%H%M%S}.hexproj", fmt::gmtime(std::chrono::system_clock::now()));
|
||||||
|
if (ProjectFile::store(path / fileName, false))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
log::info("Backed up project");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerBackgroundServices() {
|
void registerBackgroundServices() {
|
||||||
EventSettingsChanged::subscribe([]{
|
EventSettingsChanged::subscribe([]{
|
||||||
networkInterfaceServiceEnabled = bool(ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.network_interface", false));
|
networkInterfaceServiceEnabled = bool(ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.network_interface", false));
|
||||||
|
autoBackupTime = ContentRegistry::Settings::read("hex.builtin.setting.general", "hex.builtin.setting.general.auto_backup_time", 0).get<int>() * 30;
|
||||||
});
|
});
|
||||||
|
|
||||||
ContentRegistry::BackgroundServices::registerService("hex.builtin.background_service.network_interface"_lang, handleNetworkInterfaceService);
|
ContentRegistry::BackgroundServices::registerService("hex.builtin.background_service.network_interface"_lang, handleNetworkInterfaceService);
|
||||||
|
ContentRegistry::BackgroundServices::registerService("hex.builtin.background_service.auto_backup"_lang, handleAutoBackup);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -164,13 +164,13 @@ namespace hex::plugin::builtin {
|
|||||||
// If saveLocation is false, reset the project path (do not release the lock)
|
// If saveLocation is false, reset the project path (do not release the lock)
|
||||||
if (updateLocation) {
|
if (updateLocation) {
|
||||||
resetPath.release();
|
resetPath.release();
|
||||||
|
|
||||||
|
// 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");
|
AchievementManager::unlockAchievement("hex.builtin.achievement.starting_out", "hex.builtin.achievement.starting_out.save_project.name");
|
||||||
|
|
||||||
// Request, as this puts us into a project state
|
|
||||||
RequestUpdateWindowTitle::post();
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,8 +23,43 @@ namespace hex::plugin::builtin::recent {
|
|||||||
constexpr static auto MaxRecentEntries = 5;
|
constexpr static auto MaxRecentEntries = 5;
|
||||||
constexpr static auto BackupFileName = "crash_backup.hexproj";
|
constexpr static auto BackupFileName = "crash_backup.hexproj";
|
||||||
|
|
||||||
static std::atomic_bool s_recentEntriesUpdating = false;
|
namespace {
|
||||||
static std::list<RecentEntry> s_recentEntries;
|
|
||||||
|
std::atomic_bool s_recentEntriesUpdating = false;
|
||||||
|
std::list<RecentEntry> s_recentEntries;
|
||||||
|
std::atomic_bool s_autoBackupsFound = false;
|
||||||
|
|
||||||
|
|
||||||
|
class PopupAutoBackups : public Popup<PopupAutoBackups> {
|
||||||
|
public:
|
||||||
|
PopupAutoBackups() : Popup("hex.builtin.welcome.start.recent.auto_backups"_lang, true, true) { }
|
||||||
|
void drawContent() override {
|
||||||
|
if (ImGui::BeginTable("AutoBackups", 1, ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV, ImVec2(0, ImGui::GetTextLineHeightWithSpacing() * 5))) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
for (const auto &backupPath : fs::getDefaultPaths(fs::ImHexPath::Backups)) {
|
||||||
|
for (const auto &entry : std::fs::directory_iterator(backupPath)) {
|
||||||
|
if (entry.is_regular_file() && entry.path().extension() == ".hexproj") {
|
||||||
|
auto lastWriteTime = std::chrono::file_clock::to_sys(std::fs::last_write_time(entry.path()));
|
||||||
|
if (ImGui::Selectable(hex::format("hex.builtin.welcome.start.recent.auto_backups.backup"_lang, fmt::gmtime(lastWriteTime)).c_str(), false, ImGuiSelectableFlags_DontClosePopups)) {
|
||||||
|
ProjectFile::load(entry.path());
|
||||||
|
Popup::close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] ImGuiWindowFlags getFlags() const override {
|
||||||
|
return ImGuiWindowFlags_AlwaysAutoResize;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void registerEventHandlers() {
|
void registerEventHandlers() {
|
||||||
// Save every opened provider as a "recent" shortcut
|
// Save every opened provider as a "recent" shortcut
|
||||||
@ -93,7 +128,7 @@ namespace hex::plugin::builtin::recent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateRecentEntries() {
|
void updateRecentEntries() {
|
||||||
TaskManager::createBackgroundTask("Updating recent files", [](auto&){
|
TaskManager::createBackgroundTask("Updating recent files", [](auto&) {
|
||||||
if (s_recentEntriesUpdating)
|
if (s_recentEntriesUpdating)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -145,6 +180,16 @@ namespace hex::plugin::builtin::recent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::copy(uniqueProviders.begin(), uniqueProviders.end(), std::front_inserter(s_recentEntries));
|
std::copy(uniqueProviders.begin(), uniqueProviders.end(), std::front_inserter(s_recentEntries));
|
||||||
|
|
||||||
|
s_autoBackupsFound = false;
|
||||||
|
for (const auto &backupPath : fs::getDefaultPaths(fs::ImHexPath::Backups)) {
|
||||||
|
for (const auto &entry : std::fs::directory_iterator(backupPath)) {
|
||||||
|
if (entry.is_regular_file() && entry.path().extension() == ".hexproj") {
|
||||||
|
s_autoBackupsFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,13 +217,12 @@ namespace hex::plugin::builtin::recent {
|
|||||||
|
|
||||||
|
|
||||||
void draw() {
|
void draw() {
|
||||||
if (s_recentEntries.empty())
|
if (s_recentEntries.empty() && !s_autoBackupsFound)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGuiExt::BeginSubWindow("hex.builtin.welcome.start.recent"_lang, ImVec2(), ImGuiChildFlags_AutoResizeX);
|
ImGuiExt::BeginSubWindow("hex.builtin.welcome.start.recent"_lang, ImVec2(), ImGuiChildFlags_AutoResizeX);
|
||||||
{
|
{
|
||||||
if (!s_recentEntriesUpdating) {
|
if (!s_recentEntriesUpdating) {
|
||||||
|
|
||||||
for (auto it = s_recentEntries.begin(); it != s_recentEntries.end();) {
|
for (auto it = s_recentEntries.begin(); it != s_recentEntries.end();) {
|
||||||
const auto &recentEntry = *it;
|
const auto &recentEntry = *it;
|
||||||
bool shouldRemove = false;
|
bool shouldRemove = false;
|
||||||
@ -199,8 +243,38 @@ namespace hex::plugin::builtin::recent {
|
|||||||
loadRecentEntry(recentEntry);
|
loadRecentEntry(recentEntry);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!isProject)
|
|
||||||
ImGui::SetItemTooltip("%s", Lang(recentEntry.type).get().c_str());
|
if (ImGui::IsItemHovered() && ImGui::GetIO().KeyShift) {
|
||||||
|
if (ImGui::BeginTooltip()) {
|
||||||
|
if (ImGui::BeginTable("##RecentEntryTooltip", 2, ImGuiTableFlags_RowBg)) {
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("hex.builtin.common.name"_lang);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(recentEntry.displayName.c_str());
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("hex.builtin.common.type"_lang);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
|
||||||
|
if (isProject) {
|
||||||
|
ImGui::TextUnformatted("hex.builtin.common.project"_lang);
|
||||||
|
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted("hex.builtin.common.path"_lang);
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextUnformatted(recentEntry.data["path"].get<std::string>().c_str());
|
||||||
|
} else {
|
||||||
|
ImGui::TextUnformatted(Lang(recentEntry.type));
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
|
}
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Detect right click on recent provider
|
// Detect right click on recent provider
|
||||||
std::string popupID = hex::format("RecentEntryMenu.{}", recentEntry.getHash());
|
std::string popupID = hex::format("RecentEntryMenu.{}", recentEntry.getHash());
|
||||||
@ -223,6 +297,12 @@ namespace hex::plugin::builtin::recent {
|
|||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s_autoBackupsFound) {
|
||||||
|
ImGui::Separator();
|
||||||
|
if (ImGuiExt::Hyperlink(hex::format("{} {}", ICON_VS_ARCHIVE, "hex.builtin.welcome.start.recent.auto_backups"_lang).c_str()))
|
||||||
|
PopupAutoBackups::open();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGuiExt::EndSubWindow();
|
ImGuiExt::EndSubWindow();
|
||||||
|
@ -165,10 +165,10 @@ namespace hex::plugin::builtin {
|
|||||||
public:
|
public:
|
||||||
bool draw(const std::string &name) override {
|
bool draw(const std::string &name) override {
|
||||||
auto format = [this] -> std::string {
|
auto format = [this] -> std::string {
|
||||||
if (this->m_value == 0)
|
if (this->m_value == 0)
|
||||||
return "hex.builtin.setting.interface.scaling.native"_lang;
|
return "hex.builtin.setting.interface.scaling.native"_lang;
|
||||||
else
|
else
|
||||||
return "x%.1f";
|
return "x%.1f";
|
||||||
}();
|
}();
|
||||||
|
|
||||||
if (ImGui::SliderFloat(name.data(), &this->m_value, 0, 10, format.c_str(), ImGuiSliderFlags_AlwaysClamp)) {
|
if (ImGui::SliderFloat(name.data(), &this->m_value, 0, 10, format.c_str(), ImGuiSliderFlags_AlwaysClamp)) {
|
||||||
@ -191,6 +191,39 @@ namespace hex::plugin::builtin {
|
|||||||
float m_value = 0;
|
float m_value = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AutoBackupWidget : public ContentRegistry::Settings::Widgets::Widget {
|
||||||
|
public:
|
||||||
|
bool draw(const std::string &name) override {
|
||||||
|
auto format = [this] -> std::string {
|
||||||
|
auto value = this->m_value * 30;
|
||||||
|
if (value == 0)
|
||||||
|
return "hex.builtin.common.off"_lang;
|
||||||
|
else if (value < 60)
|
||||||
|
return hex::format("hex.builtin.setting.general.auto_backup_time.format.simple"_lang, value);
|
||||||
|
else
|
||||||
|
return hex::format("hex.builtin.setting.general.auto_backup_time.format.extended"_lang, value / 60, value % 60);
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (ImGui::SliderInt(name.data(), &this->m_value, 0, (30 * 60) / 30, format.c_str(), ImGuiSliderFlags_AlwaysClamp | ImGuiSliderFlags_NoInput)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load(const nlohmann::json &data) override {
|
||||||
|
if (data.is_number())
|
||||||
|
this->m_value = data.get<int>();
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json store() override {
|
||||||
|
return this->m_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class KeybindingWidget : public ContentRegistry::Settings::Widgets::Widget {
|
class KeybindingWidget : public ContentRegistry::Settings::Widgets::Widget {
|
||||||
public:
|
public:
|
||||||
KeybindingWidget(View *view, const Shortcut &shortcut) : m_view(view), m_shortcut(shortcut), m_drawShortcut(shortcut), m_defaultShortcut(shortcut) {}
|
KeybindingWidget(View *view, const Shortcut &shortcut) : m_view(view), m_shortcut(shortcut), m_drawShortcut(shortcut), m_defaultShortcut(shortcut) {}
|
||||||
@ -337,6 +370,7 @@ namespace hex::plugin::builtin {
|
|||||||
|
|
||||||
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "", "hex.builtin.setting.general.show_tips", false);
|
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "", "hex.builtin.setting.general.show_tips", false);
|
||||||
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "", "hex.builtin.setting.general.save_recent_providers", true);
|
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "", "hex.builtin.setting.general.save_recent_providers", true);
|
||||||
|
ContentRegistry::Settings::add<AutoBackupWidget>("hex.builtin.setting.general", "", "hex.builtin.setting.general.auto_backup_time");
|
||||||
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.auto_load_patterns", true);
|
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.auto_load_patterns", true);
|
||||||
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.sync_pattern_source", false);
|
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.patterns", "hex.builtin.setting.general.sync_pattern_source", false);
|
||||||
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.network", "hex.builtin.setting.general.network_interface", false);
|
ContentRegistry::Settings::add<Widgets::Checkbox>("hex.builtin.setting.general", "hex.builtin.setting.general.network", "hex.builtin.setting.general.network_interface", false);
|
||||||
|
Loading…
Reference in New Issue
Block a user