diff --git a/lib/libimhex/CMakeLists.txt b/lib/libimhex/CMakeLists.txt index 25d8e163aab6e..5cdc125cb0cda 100644 --- a/lib/libimhex/CMakeLists.txt +++ b/lib/libimhex/CMakeLists.txt @@ -36,6 +36,7 @@ set(LIBIMHEX_SOURCES source/helpers/logger.cpp source/helpers/tar.cpp source/helpers/debugging.cpp + source/helpers/default_paths.cpp source/test/tests.cpp diff --git a/lib/libimhex/include/hex/helpers/default_paths.hpp b/lib/libimhex/include/hex/helpers/default_paths.hpp new file mode 100644 index 0000000000000..e73cb3789dfe0 --- /dev/null +++ b/lib/libimhex/include/hex/helpers/default_paths.hpp @@ -0,0 +1,111 @@ +#pragma once + +#include + +#include + +namespace hex::paths { + + namespace impl { + + class DefaultPath { + protected: + constexpr DefaultPath() = default; + virtual ~DefaultPath() = default; + + public: + DefaultPath(const DefaultPath&) = delete; + DefaultPath(DefaultPath&&) = delete; + DefaultPath& operator=(const DefaultPath&) = delete; + DefaultPath& operator=(DefaultPath&&) = delete; + + virtual std::vector all() const = 0; + virtual std::vector read() const; + virtual std::vector write() const; + }; + + class ConfigPath : public DefaultPath { + public: + explicit ConfigPath(std::fs::path postfix) : m_postfix(std::move(postfix)) {} + + std::vector all() const override; + + private: + std::fs::path m_postfix; + }; + + class DataPath : public DefaultPath { + public: + explicit DataPath(std::fs::path postfix) : m_postfix(std::move(postfix)) {} + + std::vector all() const override; + std::vector write() const override; + + private: + std::fs::path m_postfix; + }; + + class PluginPath : public DefaultPath { + public: + explicit PluginPath(std::fs::path postfix) : m_postfix(std::move(postfix)) {} + + std::vector all() const override; + + private: + std::fs::path m_postfix; + }; + + } + + std::vector getDataPaths(bool includeSystemFolders); + std::vector getConfigPaths(bool includeSystemFolders); + + const static inline impl::ConfigPath Config("config"); + const static inline impl::ConfigPath Recent("recent"); + + const static inline impl::PluginPath Libraries("lib"); + const static inline impl::PluginPath Plugins("plugins"); + + const static inline impl::DataPath Patterns("patterns"); + const static inline impl::DataPath PatternsInclude("patterns/include"); + const static inline impl::DataPath Magic("magic"); + const static inline impl::DataPath Yara("yara"); + const static inline impl::DataPath YaraAdvancedAnalysis("yara/advanced_analysis"); + const static inline impl::DataPath Backups("backups"); + const static inline impl::DataPath Resources("resources"); + const static inline impl::DataPath Constants("constants"); + const static inline impl::DataPath Encodings("encodings"); + const static inline impl::DataPath Logs("logs"); + const static inline impl::DataPath Scripts("scripts"); + const static inline impl::DataPath Inspectors("scripts/inspectors"); + const static inline impl::DataPath Themes("themes"); + const static inline impl::DataPath Nodes("scripts/nodes"); + const static inline impl::DataPath Layouts("layouts"); + const static inline impl::DataPath Workspaces("workspaces"); + + constexpr static inline std::array All = { + &Config, + &Recent, + + &Libraries, + &Plugins, + + &Patterns, + &PatternsInclude, + &Magic, + &Yara, + &YaraAdvancedAnalysis, + &Backups, + &Resources, + &Constants, + &Encodings, + &Logs, + &Scripts, + &Inspectors, + &Themes, + &Nodes, + &Layouts, + &Workspaces, + }; + +} \ No newline at end of file diff --git a/lib/libimhex/include/hex/helpers/fs.hpp b/lib/libimhex/include/hex/helpers/fs.hpp index 88a5aa46e1929..80babb4664f8e 100644 --- a/lib/libimhex/include/hex/helpers/fs.hpp +++ b/lib/libimhex/include/hex/helpers/fs.hpp @@ -1,7 +1,5 @@ #pragma once -#include - #include #include #include @@ -31,36 +29,7 @@ namespace hex::fs { void openFolderExternal(const std::fs::path &dirPath); void openFolderWithSelectionExternal(const std::fs::path &selectedFilePath); - enum class ImHexPath : u32 { - Patterns = 0, - PatternsInclude, - Magic, - Plugins, - Yara, - YaraAdvancedAnalysis, - Config, - Backups, - Resources, - Constants, - Encodings, - Logs, - Recent, - Scripts, - Inspectors, - Themes, - Libraries, - Nodes, - Layouts, - Workspaces, - - END - }; bool isPathWritable(const std::fs::path &path); - std::vector getDefaultPaths(ImHexPath path, bool listNonExisting = false); - - // Temporarily expose these for the migration function - std::vector getDataPaths(); - std::vector appendPath(std::vector paths, const std::fs::path &folder); } \ No newline at end of file diff --git a/lib/libimhex/source/api/achievement_manager.cpp b/lib/libimhex/source/api/achievement_manager.cpp index 42e094ae9baef..48306745b7301 100644 --- a/lib/libimhex/source/api/achievement_manager.cpp +++ b/lib/libimhex/source/api/achievement_manager.cpp @@ -2,6 +2,7 @@ #include #include +#include #include @@ -197,7 +198,7 @@ namespace hex { constexpr static auto AchievementsFile = "achievements.json"; void AchievementManager::loadProgress() { - for (const auto &directory : fs::getDefaultPaths(fs::ImHexPath::Config)) { + for (const auto &directory : paths::Config.read()) { auto path = directory / AchievementsFile; if (!wolv::io::fs::exists(path)) { @@ -246,7 +247,7 @@ namespace hex { if (json.empty()) return; - for (const auto &directory : fs::getDefaultPaths(fs::ImHexPath::Config)) { + for (const auto &directory : paths::Config.write()) { auto path = directory / AchievementsFile; wolv::io::File file(path, wolv::io::File::Mode::Create); diff --git a/lib/libimhex/source/api/content_registry.cpp b/lib/libimhex/source/api/content_registry.cpp index 07c6478425598..c7d65b303f282 100644 --- a/lib/libimhex/source/api/content_registry.cpp +++ b/lib/libimhex/source/api/content_registry.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -101,7 +102,7 @@ namespace hex { void load() { bool loaded = false; - for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) { + for (const auto &dir : paths::Config.read()) { wolv::io::File file(dir / SettingsFile, wolv::io::File::Mode::Read); if (file.isValid()) { @@ -142,7 +143,7 @@ namespace hex { if (result.empty()) { return; } - for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) { + for (const auto &dir : paths::Config.write()) { wolv::io::File file(dir / SettingsFile, wolv::io::File::Mode::Create); if (file.isValid()) { @@ -153,7 +154,7 @@ namespace hex { } void clear() { - for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) { + for (const auto &dir : paths::Config.write()) { wolv::io::fs::remove(dir / SettingsFile); } } @@ -595,7 +596,7 @@ namespace hex { ); } - runtime.setIncludePaths(fs::getDefaultPaths(fs::ImHexPath::PatternsInclude) | fs::getDefaultPaths(fs::ImHexPath::Patterns)); + runtime.setIncludePaths(paths::PatternsInclude.read() | paths::Patterns.read()); for (const auto &[ns, name, paramCount, callback, dangerous] : impl::getFunctions()) { if (dangerous) diff --git a/lib/libimhex/source/api/layout_manager.cpp b/lib/libimhex/source/api/layout_manager.cpp index 783cc2e9e20fc..fa2beaf97de23 100644 --- a/lib/libimhex/source/api/layout_manager.cpp +++ b/lib/libimhex/source/api/layout_manager.cpp @@ -1,13 +1,15 @@ #include +#include +#include #include #include #include +#include + #include #include -#include -#include namespace hex { @@ -40,10 +42,7 @@ namespace hex { fileName += ".hexlyt"; std::fs::path layoutPath; - for (const auto &path : hex::fs::getDefaultPaths(fs::ImHexPath::Layouts)) { - if (!hex::fs::isPathWritable(path)) - continue; - + for (const auto &path : paths::Layouts.write()) { layoutPath = path / fileName; } @@ -109,7 +108,7 @@ namespace hex { void LayoutManager::reload() { s_layouts->clear(); - for (const auto &directory : hex::fs::getDefaultPaths(fs::ImHexPath::Layouts)) { + for (const auto &directory : paths::Layouts.read()) { for (const auto &entry : std::fs::directory_iterator(directory)) { const auto &path = entry.path(); diff --git a/lib/libimhex/source/api/plugin_manager.cpp b/lib/libimhex/source/api/plugin_manager.cpp index e466163836824..884fff3cf4fe5 100644 --- a/lib/libimhex/source/api/plugin_manager.cpp +++ b/lib/libimhex/source/api/plugin_manager.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -306,7 +307,7 @@ namespace hex { bool PluginManager::loadLibraries() { bool success = true; - for (const auto &loadPath : fs::getDefaultPaths(fs::ImHexPath::Libraries)) + for (const auto &loadPath : paths::Libraries.read()) success = PluginManager::loadLibraries(loadPath) && success; return success; diff --git a/lib/libimhex/source/api/workspace_manager.cpp b/lib/libimhex/source/api/workspace_manager.cpp index c7fa465f6ef18..655e8dd31fcf6 100644 --- a/lib/libimhex/source/api/workspace_manager.cpp +++ b/lib/libimhex/source/api/workspace_manager.cpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -25,7 +26,7 @@ namespace hex { .builtin = false }).first; - for (const auto &workspaceFolder : fs::getDefaultPaths(fs::ImHexPath::Workspaces)) { + for (const auto &workspaceFolder : paths::Workspaces.write()) { const auto workspacePath = workspaceFolder / (name + ".hexws"); if (exportToFile(workspacePath)) { s_currentWorkspace->second.path = workspacePath; @@ -157,7 +158,7 @@ namespace hex { void WorkspaceManager::reload() { WorkspaceManager::reset(); - for (const auto &defaultPath : fs::getDefaultPaths(fs::ImHexPath::Workspaces)) { + for (const auto &defaultPath : paths::Workspaces.read()) { for (const auto &entry : std::fs::directory_iterator(defaultPath)) { if (!entry.is_regular_file()) { continue; diff --git a/lib/libimhex/source/helpers/default_paths.cpp b/lib/libimhex/source/helpers/default_paths.cpp new file mode 100644 index 0000000000000..43f9a72b9e213 --- /dev/null +++ b/lib/libimhex/source/helpers/default_paths.cpp @@ -0,0 +1,150 @@ +#include + +#include +#include + +#if defined(OS_WINDOWS) + #include + #include +#elif defined(OS_LINUX) || defined(OS_WEB) + #include +# endif + +namespace hex::paths { + + std::vector getDataPaths(bool includeSystemFolders) { + std::vector paths; + + #if defined(OS_WINDOWS) + + // In the portable Windows version, we just use the executable directory + // Prevent the use of the AppData folder here + if (!ImHexApi::System::isPortableVersion()) { + PWSTR wAppDataPath = nullptr; + if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath))) { + paths.emplace_back(wAppDataPath); + CoTaskMemFree(wAppDataPath); + } + } + + #elif defined(OS_MACOS) + + paths.push_back(wolv::io::fs::getApplicationSupportDirectoryPath()); + + #elif defined(OS_LINUX) || defined(OS_WEB) + + paths.push_back(xdg::DataHomeDir()); + + auto dataDirs = xdg::DataDirs(); + std::copy(dataDirs.begin(), dataDirs.end(), std::back_inserter(paths)); + + #endif + + #if defined(OS_MACOS) + + if (includeSystemFolders) { + if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) { + paths.push_back(*executablePath); + } + } + + #else + + for (auto &path : paths) + path = path / "imhex"; + + if (ImHexApi::System::isPortableVersion() || includeSystemFolders) { + if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) + paths.push_back(executablePath->parent_path()); + } + + #endif + + + // Add additional data directories to the path + auto additionalDirs = ImHexApi::System::getAdditionalFolderPaths(); + std::ranges::copy(additionalDirs, std::back_inserter(paths)); + + // Add the project file directory to the path, if one is loaded + if (ProjectFile::hasPath()) { + paths.push_back(ProjectFile::getPath().parent_path()); + } + + return paths; + } + + std::vector getConfigPaths(bool includeSystemFolders) { + #if defined(OS_WINDOWS) + return getDataPaths(includeSystemFolders); + #elif defined(OS_MACOS) + return getDataPaths(includeSystemFolders); + #elif defined(OS_LINUX) || defined(OS_WEB) + return {xdg::ConfigHomeDir() / "imhex"}; + #endif + } + + static std::vector appendPath(std::vector paths, const std::fs::path &folder) { + for (auto &path : paths) + path = path / folder; + + return paths; + } + + static std::vector getPluginPaths() { + std::vector paths = getDataPaths(true); + + // Add the system plugin directory to the path if one was provided at compile time + #if defined(OS_LINUX) && defined(SYSTEM_PLUGINS_LOCATION) + paths.push_back(SYSTEM_PLUGINS_LOCATION); + #endif + + return paths; + } + + namespace impl { + + std::vector DefaultPath::read() const { + auto result = this->all(); + + std::erase_if(result, [](const auto &entryPath) { + return !wolv::io::fs::isDirectory(entryPath); + }); + + return result; + } + + std::vector DefaultPath::write() const { + auto result = this->read(); + + std::erase_if(result, [](const auto &entryPath) { + return !hex::fs::isPathWritable(entryPath); + }); + + return result; + } + + std::vector ConfigPath::all() const { + return appendPath(getConfigPaths(false), m_postfix); + } + + std::vector DataPath::all() const { + return appendPath(getConfigPaths(true), m_postfix); + } + + std::vector DataPath::write() const { + auto result = appendPath(getConfigPaths(false), m_postfix); + + std::erase_if(result, [](const auto &entryPath) { + return !hex::fs::isPathWritable(entryPath); + }); + + return result; + } + + std::vector PluginPath::all() const { + return appendPath(getPluginPaths(), m_postfix); + } + + } + +} \ No newline at end of file diff --git a/lib/libimhex/source/helpers/fs.cpp b/lib/libimhex/source/helpers/fs.cpp index 2027fa771caf6..50de4f63d1a06 100644 --- a/lib/libimhex/source/helpers/fs.cpp +++ b/lib/libimhex/source/helpers/fs.cpp @@ -286,170 +286,6 @@ namespace hex::fs { #endif - std::vector getDataPaths() { - std::vector paths; - - #if defined(OS_WINDOWS) - - // In the portable Windows version, we just use the executable directory - // Prevent the use of the AppData folder here - if (!ImHexApi::System::isPortableVersion()) { - PWSTR wAppDataPath = nullptr; - if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath))) { - paths.emplace_back(wAppDataPath); - CoTaskMemFree(wAppDataPath); - } - } - - #elif defined(OS_MACOS) - - paths.push_back(wolv::io::fs::getApplicationSupportDirectoryPath()); - - #elif defined(OS_LINUX) || defined(OS_WEB) - - paths.push_back(xdg::DataHomeDir()); - - auto dataDirs = xdg::DataDirs(); - std::copy(dataDirs.begin(), dataDirs.end(), std::back_inserter(paths)); - - #endif - - #if defined(OS_MACOS) - - if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) - paths.push_back(*executablePath); - - #else - - for (auto &path : paths) - path = path / "imhex"; - - if (auto executablePath = wolv::io::fs::getExecutablePath(); executablePath.has_value()) - paths.push_back(executablePath->parent_path()); - - #endif - - - // Add additional data directories to the path - auto additionalDirs = ImHexApi::System::getAdditionalFolderPaths(); - std::ranges::copy(additionalDirs, std::back_inserter(paths)); - - // Add the project file directory to the path, if one is loaded - if (ProjectFile::hasPath()) { - paths.push_back(ProjectFile::getPath().parent_path()); - } - - return paths; - } - - static std::vector getConfigPaths() { - #if defined(OS_WINDOWS) - return getDataPaths(); - #elif defined(OS_MACOS) - return getDataPaths(); - #elif defined(OS_LINUX) || defined(OS_WEB) - return {xdg::ConfigHomeDir() / "imhex"}; - #endif - } - - std::vector appendPath(std::vector paths, const std::fs::path &folder) { - for (auto &path : paths) - path = path / folder; - - return paths; - } - - std::vector getPluginPaths() { - std::vector paths = getDataPaths(); - - // Add the system plugin directory to the path if one was provided at compile time - #if defined(OS_LINUX) && defined(SYSTEM_PLUGINS_LOCATION) - paths.push_back(SYSTEM_PLUGINS_LOCATION); - #endif - - return paths; - } - - - std::vector getDefaultPaths(ImHexPath path, bool listNonExisting) { - std::vector result; - - // Return the correct path based on the ImHexPath enum - switch (path) { - case ImHexPath::END: - return { }; - case ImHexPath::Constants: - result = appendPath(getDataPaths(), "constants"); - break; - case ImHexPath::Config: - result = appendPath(getConfigPaths(), "config"); - break; - case ImHexPath::Backups: - result = appendPath(getDataPaths(), "backups"); - break; - case ImHexPath::Encodings: - result = appendPath(getDataPaths(), "encodings"); - break; - case ImHexPath::Logs: - result = appendPath(getDataPaths(), "logs"); - break; - case ImHexPath::Plugins: - result = appendPath(getPluginPaths(), "plugins"); - break; - case ImHexPath::Libraries: - result = appendPath(getPluginPaths(), "lib"); - break; - case ImHexPath::Resources: - result = appendPath(getDataPaths(), "resources"); - break; - case ImHexPath::Magic: - result = appendPath(getDataPaths(), "magic"); - break; - case ImHexPath::Patterns: - result = appendPath(getDataPaths(), "patterns"); - break; - case ImHexPath::PatternsInclude: - result = appendPath(getDataPaths(), "includes"); - break; - case ImHexPath::Yara: - result = appendPath(getDataPaths(), "yara"); - break; - case ImHexPath::YaraAdvancedAnalysis: - result = appendPath(getDefaultPaths(ImHexPath::Yara), "advanced_analysis"); - break; - case ImHexPath::Recent: - result = appendPath(getConfigPaths(), "recent"); - break; - case ImHexPath::Scripts: - result = appendPath(getDataPaths(), "scripts"); - break; - case ImHexPath::Inspectors: - result = appendPath(getDefaultPaths(ImHexPath::Scripts), "inspectors"); - break; - case ImHexPath::Nodes: - result = appendPath(getDefaultPaths(ImHexPath::Scripts), "nodes"); - break; - case ImHexPath::Themes: - result = appendPath(getDataPaths(), "themes"); - break; - case ImHexPath::Layouts: - result = appendPath(getDataPaths(), "layouts"); - break; - case ImHexPath::Workspaces: - result = appendPath(getDataPaths(), "workspaces"); - break; - } - - // Remove all paths that don't exist if requested - if (!listNonExisting) { - std::erase_if(result, [](const auto &entryPath) { - return !wolv::io::fs::isDirectory(entryPath); - }); - } - - return result; - } - bool isPathWritable(const std::fs::path &path) { constexpr static auto TestFileName = "__imhex__tmp__"; diff --git a/lib/libimhex/source/helpers/logger.cpp b/lib/libimhex/source/helpers/logger.cpp index d27220cb0a8a2..23e348c2392dd 100644 --- a/lib/libimhex/source/helpers/logger.cpp +++ b/lib/libimhex/source/helpers/logger.cpp @@ -2,8 +2,10 @@ #include #include + #include #include +#include #include @@ -80,7 +82,7 @@ namespace hex::log { void redirectToFile() { if (s_loggerFile.isValid()) return; - for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Logs, true)) { + for (const auto &path : paths::Logs.all()) { wolv::io::fs::createDirectories(path); s_loggerFile = wolv::io::File(path / hex::format("{0:%Y%m%d_%H%M%S}.log", fmt::localtime(std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()))), wolv::io::File::Mode::Create); s_loggerFile.disableBuffering(); diff --git a/lib/libimhex/source/helpers/magic.cpp b/lib/libimhex/source/helpers/magic.cpp index 15af7e3f4e753..aa6fe70ab452d 100644 --- a/lib/libimhex/source/helpers/magic.cpp +++ b/lib/libimhex/source/helpers/magic.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -29,7 +30,7 @@ namespace hex::magic { std::string magicFiles; std::error_code error; - for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Magic)) { + for (const auto &dir : paths::Magic.read()) { for (const auto &entry : std::fs::directory_iterator(dir, error)) { auto path = std::fs::absolute(entry.path()); @@ -64,12 +65,12 @@ namespace hex::magic { if (magicFiles->empty()) return true; - std::array cwd = { 0x00 }; + std::array cwd = { }; if (getcwd(cwd.data(), cwd.size()) == nullptr) return false; std::optional magicFolder; - for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Magic)) { + for (const auto &dir : paths::Magic.write()) { if (std::fs::exists(dir) && fs::isPathWritable(dir)) { magicFolder = dir; break; diff --git a/main/gui/source/crash_handlers.cpp b/main/gui/source/crash_handlers.cpp index 574b50073b342..76270e637aebd 100644 --- a/main/gui/source/crash_handlers.cpp +++ b/main/gui/source/crash_handlers.cpp @@ -2,19 +2,19 @@ #include #include -#include #include #include +#include #include #include - -#include - +#include #include + #include +#include #include #include @@ -48,7 +48,7 @@ namespace hex::crash { { "project", wolv::io::fs::toNormalizedPathString(ProjectFile::getPath()) }, }; - for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Config)) { + for (const auto &path : paths::Config.write()) { wolv::io::File file(path / "crash.json", wolv::io::File::Mode::Create); if (file.isValid()) { file.writeString(crashData.dump(4)); @@ -194,7 +194,7 @@ namespace hex::crash { // Create crash backup if any providers are open if (ImHexApi::Provider::isValid()) { - for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Config)) { + for (const auto &path : paths::Config.write()) { if (ProjectFile::store(path / CrashBackupFileName, false)) break; } diff --git a/main/gui/source/init/run/cli.cpp b/main/gui/source/init/run/cli.cpp index bde9c1ba8b405..4090b9d9f23d0 100644 --- a/main/gui/source/init/run/cli.cpp +++ b/main/gui/source/init/run/cli.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -60,7 +61,7 @@ namespace hex::init { // Load all plugins but don't initialize them PluginManager::loadLibraries(); - for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Plugins)) { + for (const auto &dir : paths::Plugins.read()) { PluginManager::load(dir); } diff --git a/main/gui/source/init/tasks.cpp b/main/gui/source/init/tasks.cpp index 5427e391c0c2c..cd1e1f459d42f 100644 --- a/main/gui/source/init/tasks.cpp +++ b/main/gui/source/init/tasks.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -33,11 +34,9 @@ namespace hex::init { bool createDirectories() { bool result = true; - using enum fs::ImHexPath; - // Try to create all default directories - for (u32 path = 0; path < u32(fs::ImHexPath::END); path++) { - for (auto &folder : fs::getDefaultPaths(static_cast(path), true)) { + for (auto path : paths::All) { + for (auto &folder : path->all()) { try { wolv::io::fs::createDirectories(folder); } catch (...) { @@ -95,7 +94,7 @@ namespace hex::init { bool loadPlugins() { // Load all plugins #if !defined(IMHEX_STATIC_LINK_PLUGINS) - for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Plugins)) { + for (const auto &dir : paths::Plugins.read()) { PluginManager::addLoadPath(dir); } @@ -185,8 +184,8 @@ namespace hex::init { bool deleteOldFiles() { bool result = true; - auto keepNewest = [&](u32 count, fs::ImHexPath pathType) { - for (const auto &path : fs::getDefaultPaths(pathType)) { + auto keepNewest = [&](u32 count, const paths::impl::DefaultPath &pathType) { + for (const auto &path : pathType.write()) { try { std::vector files; @@ -209,8 +208,8 @@ namespace hex::init { } }; - keepNewest(10, fs::ImHexPath::Logs); - keepNewest(25, fs::ImHexPath::Backups); + keepNewest(10, paths::Logs); + keepNewest(25, paths::Backups); return result; } diff --git a/main/gui/source/window/macos_window.cpp b/main/gui/source/window/macos_window.cpp index f51047d6c7ff4..5f57df817e735 100644 --- a/main/gui/source/window/macos_window.cpp +++ b/main/gui/source/window/macos_window.cpp @@ -1,14 +1,14 @@ -#include - #include "window.hpp" #if defined(OS_MACOS) + #include #include #include #include #include + #include #include #include @@ -35,7 +35,7 @@ namespace hex { log::impl::enableColorPrinting(); // Add plugin library folders to dll search path - for (const auto &path : hex::fs::getDefaultPaths(fs::ImHexPath::Libraries)) { + for (const auto &path : paths::Libraries.read()) { if (std::fs::exists(path)) setenv("LD_LIBRARY_PATH", hex::format("{};{}", hex::getEnvironmentVariable("LD_LIBRARY_PATH").value_or(""), path.string().c_str()).c_str(), true); } diff --git a/main/gui/source/window/win_window.cpp b/main/gui/source/window/win_window.cpp index 13067dca37fa1..4c7687f62e035 100644 --- a/main/gui/source/window/win_window.cpp +++ b/main/gui/source/window/win_window.cpp @@ -1,11 +1,13 @@ #include "window.hpp" -#include "messaging.hpp" #if defined(OS_WINDOWS) - #include + #include "messaging.hpp" + +#include #include + #include #include #include @@ -352,7 +354,7 @@ namespace hex { } // Add plugin library folders to dll search path - for (const auto &path : hex::fs::getDefaultPaths(fs::ImHexPath::Libraries)) { + for (const auto &path : paths::Libraries.read()) { if (std::fs::exists(path)) AddDllDirectory(path.c_str()); } diff --git a/main/gui/source/window/window.cpp b/main/gui/source/window/window.cpp index 783a82f0378b3..4717b3599c305 100644 --- a/main/gui/source/window/window.cpp +++ b/main/gui/source/window/window.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -331,7 +332,7 @@ namespace hex { ImGui::TableHeadersRow(); - for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Plugins, true)) { + for (const auto &path : paths::Plugins.all()) { const auto filePath = path / "builtin.hexplug"; ImGui::TableNextRow(); ImGui::TableNextColumn(); @@ -867,8 +868,11 @@ namespace hex { // If the key name is only one character long, use the ASCII value instead // Otherwise the keyboard was set to a non-English layout and the key name // is not the same as the ASCII value - if (name.length() == 1) { - key = std::toupper(name[0]); + if (!name.empty()) { + const std::uint8_t byte = name[0]; + if (name.length() == 1 && byte <= 0x7F) { + key = std::toupper(byte); + } } } diff --git a/main/updater/source/main.cpp b/main/updater/source/main.cpp index d9593bfeea933..59f5344b60308 100644 --- a/main/updater/source/main.cpp +++ b/main/updater/source/main.cpp @@ -3,6 +3,7 @@ #include #include +#include using namespace std::literals::string_literals; @@ -46,7 +47,7 @@ std::optional downloadUpdate(const std::string &url) { // Loop over all available paths wolv::io::File file; - for (const auto &path : hex::fs::getDefaultPaths(hex::fs::ImHexPath::Config)) { + for (const auto &path : hex::paths::Config.write()) { // Remove any existing update files wolv::io::fs::remove(path / UpdateFileName); diff --git a/plugins/builtin/include/content/views/view_pattern_editor.hpp b/plugins/builtin/include/content/views/view_pattern_editor.hpp index 70b45506ce8ea..9044b158c1b54 100644 --- a/plugins/builtin/include/content/views/view_pattern_editor.hpp +++ b/plugins/builtin/include/content/views/view_pattern_editor.hpp @@ -1,8 +1,10 @@ #pragma once +#include #include -#include #include +#include +#include #include #include @@ -14,8 +16,7 @@ #include #include -#include "popups/popup_file_chooser.hpp" -#include "hex/api/achievement_manager.hpp" +#include namespace pl::ptrn { class Pattern; } @@ -261,9 +262,9 @@ namespace hex::plugin::builtin { void registerMenuItems(); void registerHandlers(); - std::function importPatternFile = [&] { + std::function m_importPatternFile = [this] { auto provider = ImHexApi::Provider::get(); - const auto basePaths = fs::getDefaultPaths(fs::ImHexPath::Patterns); + const auto basePaths = paths::Patterns.read(); std::vector paths; for (const auto &imhexPath : basePaths) { @@ -284,7 +285,7 @@ namespace hex::plugin::builtin { ); }; - std::function exportPatternFile = [&] { + std::function m_exportPatternFile = [this] { fs::openFileBrowser( fs::DialogMode::Save, { {"Pattern", "hexpat"} }, [this](const auto &path) { diff --git a/plugins/builtin/include/content/views/view_store.hpp b/plugins/builtin/include/content/views/view_store.hpp index 2c88493d2d945..2d41b3011fe3f 100644 --- a/plugins/builtin/include/content/views/view_store.hpp +++ b/plugins/builtin/include/content/views/view_store.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -40,7 +41,7 @@ namespace hex::plugin::builtin { struct StoreCategory { UnlocalizedString unlocalizedName; std::string requestName; - fs::ImHexPath path; + const paths::impl::DefaultPath* path; std::vector entries; std::function downloadCallback; }; @@ -66,10 +67,10 @@ namespace hex::plugin::builtin { void refresh(); void parseResponse(); - void addCategory(const UnlocalizedString &unlocalizedName, const std::string &requestName, fs::ImHexPath path, std::function downloadCallback = []{}); + void addCategory(const UnlocalizedString &unlocalizedName, const std::string &requestName, const paths::impl::DefaultPath *path, std::function downloadCallback = []{}); - bool download(fs::ImHexPath pathType, const std::string &fileName, const std::string &url); - bool remove(fs::ImHexPath pathType, const std::string &fileName); + bool download(const paths::impl::DefaultPath *pathType, const std::string &fileName, const std::string &url); + bool remove(const paths::impl::DefaultPath *pathType, const std::string &fileName); private: HttpRequest m_httpRequest = HttpRequest("GET", ""); diff --git a/plugins/builtin/source/content/background_services.cpp b/plugins/builtin/source/content/background_services.cpp index 234aabfc0c561..3501c726aedef 100644 --- a/plugins/builtin/source/content/background_services.cpp +++ b/plugins/builtin/source/content/background_services.cpp @@ -3,16 +3,17 @@ #include #include -#include -#include - #include -#include +#include #include #include -#include +#include #include +#include + +#include +#include namespace hex::plugin::builtin { @@ -82,7 +83,7 @@ namespace hex::plugin::builtin { } } - for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Backups)) { + for (const auto &path : paths::Backups.write()) { const auto backupPath = path / hex::format("auto_backup.{:%y%m%d_%H%M%S}.hexproj", fmt::gmtime(std::chrono::system_clock::now())); if (ProjectFile::store(backupPath, false)) { log::info("Created auto-backup file '{}'", wolv::util::toUTF8String(backupPath)); diff --git a/plugins/builtin/source/content/command_line_interface.cpp b/plugins/builtin/source/content/command_line_interface.cpp index 28d32da1883c9..76f209c206670 100644 --- a/plugins/builtin/source/content/command_line_interface.cpp +++ b/plugins/builtin/source/content/command_line_interface.cpp @@ -3,19 +3,19 @@ #include #include #include +#include +#include #include - #include #include #include #include -#include +#include -#include -#include #include +#include #include #include @@ -308,7 +308,7 @@ namespace hex::plugin::builtin { if (processedArgs.empty()) { processedArgs.emplace_back("--help"); } else { - for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::PatternsInclude)) + for (const auto &path : paths::PatternsInclude.read()) processedArgs.emplace_back(hex::format("--includes={}", wolv::util::toUTF8String(path))); } diff --git a/plugins/builtin/source/content/file_extraction.cpp b/plugins/builtin/source/content/file_extraction.cpp index aebf50c43c9f9..d2e1801bfba3e 100644 --- a/plugins/builtin/source/content/file_extraction.cpp +++ b/plugins/builtin/source/content/file_extraction.cpp @@ -4,6 +4,7 @@ #include #include +#include namespace hex::plugin::builtin { @@ -17,7 +18,7 @@ namespace hex::plugin::builtin { for (const auto &[extractFolder, alwaysExtract] : Paths) { for (const auto &romfsPath : romfs::list(extractFolder)) { - for (const auto &imhexPath : fs::getDataPaths()) { + for (const auto &imhexPath : paths::getDataPaths(false)) { const auto path = imhexPath / std::fs::relative(romfsPath, extractFolder); log::info("Extracting {} to {}", romfsPath.string(), path.string()); if (!alwaysExtract && wolv::io::fs::exists(path)) diff --git a/plugins/builtin/source/content/file_handlers.cpp b/plugins/builtin/source/content/file_handlers.cpp index 5bbb27e550632..0d74d1eaad6e3 100644 --- a/plugins/builtin/source/content/file_handlers.cpp +++ b/plugins/builtin/source/content/file_handlers.cpp @@ -1,6 +1,8 @@ #include - #include + +#include + #include namespace hex::plugin::builtin { @@ -12,7 +14,7 @@ namespace hex::plugin::builtin { }); ContentRegistry::FileHandler::add({ ".hexlyt" }, [](const std::fs::path &path) { - for (const auto &folder : fs::getDefaultPaths(fs::ImHexPath::Layouts)) { + for (const auto &folder : paths::Layouts.write()) { if (wolv::io::fs::copyFile(path, folder / path.filename())) return true; } @@ -21,7 +23,7 @@ namespace hex::plugin::builtin { }); ContentRegistry::FileHandler::add({ ".mgc" }, [](const auto &path) { - for (const auto &destPath : fs::getDefaultPaths(fs::ImHexPath::Magic)) { + for (const auto &destPath : paths::Magic.write()) { if (wolv::io::fs::copyFile(path, destPath / path.filename(), std::fs::copy_options::overwrite_existing)) { ui::ToastInfo::open("hex.builtin.view.information.magic_db_added"_lang); return true; diff --git a/plugins/builtin/source/content/project.cpp b/plugins/builtin/source/content/project.cpp index 1d85f07ca41ee..951e23701012b 100644 --- a/plugins/builtin/source/content/project.cpp +++ b/plugins/builtin/source/content/project.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -177,6 +178,10 @@ namespace hex::plugin::builtin { } void registerProjectHandlers() { - hex::ProjectFile::setProjectFunctions(load, store); + hex::ProjectFile::setProjectFunctions(load, store); + + ContentRegistry::Interface::addSidebarItem(ICON_VS_PROJECT, [] { + ImGui::TextUnformatted("Test"); + }); } } diff --git a/plugins/builtin/source/content/recent.cpp b/plugins/builtin/source/content/recent.cpp index ca52241f409c5..161ad2b3f2445 100644 --- a/plugins/builtin/source/content/recent.cpp +++ b/plugins/builtin/source/content/recent.cpp @@ -1,4 +1,3 @@ - #include #include @@ -7,6 +6,7 @@ #include #include #include +#include #include #include @@ -41,7 +41,7 @@ namespace hex::plugin::builtin::recent { }; public: PopupAutoBackups() : Popup("hex.builtin.welcome.start.recent.auto_backups", true, true) { - for (const auto &backupPath : fs::getDefaultPaths(fs::ImHexPath::Backups)) { + 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); @@ -99,7 +99,7 @@ namespace hex::plugin::builtin::recent { return; // The recent provider is saved to every "recent" directory - for (const auto &recentPath : fs::getDefaultPaths(fs::ImHexPath::Recent)) { + for (const auto &recentPath : paths::Recent.write()) { wolv::io::File recentFile(recentPath / fileName, wolv::io::File::Mode::Create); if (!recentFile.isValid()) continue; @@ -129,7 +129,7 @@ namespace hex::plugin::builtin::recent { return; // The recent provider is saved to every "recent" directory - for (const auto &recentPath : fs::getDefaultPaths(fs::ImHexPath::Recent)) { + for (const auto &recentPath : paths::Recent.write()) { wolv::io::File recentFile(recentPath / fileName, wolv::io::File::Mode::Create); if (!recentFile.isValid()) continue; @@ -160,7 +160,7 @@ namespace hex::plugin::builtin::recent { // Query all recent providers std::vector recentFilePaths; - for (const auto &folder : fs::getDefaultPaths(fs::ImHexPath::Recent)) { + for (const auto &folder : paths::Recent.read()) { for (const auto &entry : std::fs::directory_iterator(folder)) { if (entry.is_regular_file()) recentFilePaths.push_back(entry.path()); @@ -203,7 +203,7 @@ namespace hex::plugin::builtin::recent { 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 &backupPath : paths::Backups.read()) { for (const auto &entry : std::fs::directory_iterator(backupPath)) { if (entry.is_regular_file() && entry.path().extension() == ".hexproj") { s_autoBackupsFound = true; @@ -347,7 +347,7 @@ namespace hex::plugin::builtin::recent { s_recentEntries.clear(); // Remove all recent files - for (const auto &recentPath : fs::getDefaultPaths(fs::ImHexPath::Recent)) { + for (const auto &recentPath : paths::Recent.write()) { for (const auto &entry : std::fs::directory_iterator(recentPath)) std::fs::remove(entry.path()); } diff --git a/plugins/builtin/source/content/themes.cpp b/plugins/builtin/source/content/themes.cpp index 196f850778daf..82aa856e41447 100644 --- a/plugins/builtin/source/content/themes.cpp +++ b/plugins/builtin/source/content/themes.cpp @@ -1,17 +1,16 @@ #include +#include + +#include +#include #include #include #include -#include #include #include #include -#include - -#include - #include namespace hex::plugin::builtin { @@ -369,7 +368,7 @@ namespace hex::plugin::builtin { } // Load user themes - for (const auto &themeFolder : fs::getDefaultPaths(fs::ImHexPath::Themes)) { + for (const auto &themeFolder : paths::Themes.read()) { for (const auto &theme : std::fs::directory_iterator(themeFolder)) { if (theme.is_regular_file()) ThemeManager::addTheme(wolv::io::File(theme.path(), wolv::io::File::Mode::Read).readString()); diff --git a/plugins/builtin/source/content/views/view_about.cpp b/plugins/builtin/source/content/views/view_about.cpp index de1cf311b7dda..4b0228694f29a 100644 --- a/plugins/builtin/source/content/views/view_about.cpp +++ b/plugins/builtin/source/content/views/view_about.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -451,28 +452,28 @@ namespace hex::plugin::builtin { void ViewAbout::drawPathsPage() { - constexpr static std::array, size_t(fs::ImHexPath::END)> PathTypes = { + constexpr static std::array, paths::All.size()> PathTypes = { { - { "Patterns", fs::ImHexPath::Patterns }, - { "Patterns Includes", fs::ImHexPath::PatternsInclude }, - { "Magic", fs::ImHexPath::Magic }, - { "Plugins", fs::ImHexPath::Plugins }, - { "Yara Patterns", fs::ImHexPath::Yara }, - { "Yara Advaned Analysis", fs::ImHexPath::YaraAdvancedAnalysis }, - { "Config", fs::ImHexPath::Config }, - { "Backups", fs::ImHexPath::Backups }, - { "Resources", fs::ImHexPath::Resources }, - { "Constants lists", fs::ImHexPath::Constants }, - { "Custom encodings", fs::ImHexPath::Encodings }, - { "Logs", fs::ImHexPath::Logs }, - { "Recent files", fs::ImHexPath::Recent }, - { "Scripts", fs::ImHexPath::Scripts }, - { "Data inspector scripts", fs::ImHexPath::Inspectors }, - { "Themes", fs::ImHexPath::Themes }, - { "Native Libraries", fs::ImHexPath::Libraries }, - { "Custom data processor nodes", fs::ImHexPath::Nodes }, - { "Layouts", fs::ImHexPath::Layouts }, - { "Workspaces", fs::ImHexPath::Workspaces }, + { "Patterns", &paths::Patterns }, + { "Patterns Includes", &paths::PatternsInclude }, + { "Magic", &paths::Magic }, + { "Plugins", &paths::Plugins }, + { "Yara Patterns", &paths::Yara }, + { "Yara Advaned Analysis", &paths::YaraAdvancedAnalysis }, + { "Config", &paths::Config }, + { "Backups", &paths::Backups }, + { "Resources", &paths::Resources }, + { "Constants lists", &paths::Constants }, + { "Custom encodings", &paths::Encodings }, + { "Logs", &paths::Logs }, + { "Recent files", &paths::Recent }, + { "Scripts", &paths::Scripts }, + { "Data inspector scripts", &paths::Inspectors }, + { "Themes", &paths::Themes }, + { "Native Libraries", &paths::Libraries }, + { "Custom data processor nodes", &paths::Nodes }, + { "Layouts", &paths::Layouts }, + { "Workspaces", &paths::Workspaces }, } }; static_assert(PathTypes.back().first != nullptr, "All path items need to be populated!"); @@ -487,13 +488,13 @@ namespace hex::plugin::builtin { // Draw the table ImGui::TableHeadersRow(); - for (const auto &[name, type] : PathTypes) { + for (const auto &[name, paths] : PathTypes) { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::TextUnformatted(name); ImGui::TableNextColumn(); - for (auto &path : fs::getDefaultPaths(type, true)){ + for (auto &path : paths->all()){ // Draw hyperlink to paths that exist or red text if they don't if (wolv::io::fs::isDirectory(path)){ if (ImGuiExt::Hyperlink(wolv::util::toUTF8String(path).c_str())) { diff --git a/plugins/builtin/source/content/views/view_constants.cpp b/plugins/builtin/source/content/views/view_constants.cpp index ea176fa88660f..9268d87044cc2 100644 --- a/plugins/builtin/source/content/views/view_constants.cpp +++ b/plugins/builtin/source/content/views/view_constants.cpp @@ -1,8 +1,8 @@ #include "content/views/view_constants.hpp" -#include #include #include +#include #include #include @@ -22,7 +22,7 @@ namespace hex::plugin::builtin { m_constants.clear(); m_filterIndices.clear(); - for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Constants)) { + for (const auto &path : paths::Constants.read()) { if (!wolv::io::fs::exists(path)) continue; std::error_code error; diff --git a/plugins/builtin/source/content/views/view_data_inspector.cpp b/plugins/builtin/source/content/views/view_data_inspector.cpp index 9eada63167df3..8707aa09a042d 100644 --- a/plugins/builtin/source/content/views/view_data_inspector.cpp +++ b/plugins/builtin/source/content/views/view_data_inspector.cpp @@ -1,13 +1,12 @@ #include "content/views/view_data_inspector.hpp" -#include - -#include - #include +#include #include +#include #include +#include #include #include @@ -134,7 +133,7 @@ namespace hex::plugin::builtin { m_runtime.setStartAddress(m_startAddress); // Loop over all files in the inspectors folder and execute them - for (const auto &folderPath : fs::getDefaultPaths(fs::ImHexPath::Inspectors)) { + for (const auto &folderPath : paths::Inspectors.read()) { for (const auto &entry: std::fs::recursive_directory_iterator(folderPath)) { const auto &filePath = entry.path(); // Skip non-files and files that don't end with .hexpat diff --git a/plugins/builtin/source/content/views/view_data_processor.cpp b/plugins/builtin/source/content/views/view_data_processor.cpp index d014719a0437f..a97bcfb6ad715 100644 --- a/plugins/builtin/source/content/views/view_data_processor.cpp +++ b/plugins/builtin/source/content/views/view_data_processor.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -127,7 +128,7 @@ namespace hex::plugin::builtin { void process() override { switch (this->getType()) { case dp::Attribute::Type::Integer: m_value = this->getIntegerOnInput(0); break; - case dp::Attribute::Type::Float: m_value = this->getFloatOnInput(0); break; + case dp::Attribute::Type::Float: m_value = static_cast(this->getFloatOnInput(0)); break; case dp::Attribute::Type::Buffer: m_value = this->getBufferOnInput(0); break; } } @@ -568,7 +569,7 @@ namespace hex::plugin::builtin { m_customNodes.clear(); // Loop over all custom node folders - for (const auto &basePath : fs::getDefaultPaths(fs::ImHexPath::Nodes)) { + for (const auto &basePath : paths::Nodes.read()) { // Loop over all files in the folder for (const auto &entry : std::fs::recursive_directory_iterator(basePath)) { // Skip files that are not .hexnode files diff --git a/plugins/builtin/source/content/views/view_hex_editor.cpp b/plugins/builtin/source/content/views/view_hex_editor.cpp index 6106f0c49f49d..093a88566bc4d 100644 --- a/plugins/builtin/source/content/views/view_hex_editor.cpp +++ b/plugins/builtin/source/content/views/view_hex_editor.cpp @@ -7,6 +7,7 @@ #include #include +#include #include @@ -19,7 +20,6 @@ #include #include #include -#include #include using namespace std::literals::string_literals; @@ -1053,7 +1053,7 @@ namespace hex::plugin::builtin { /* Load Encoding File */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.import", "hex.builtin.menu.file.import.custom_encoding" }, "あ", 5050, Shortcut::None, [this]{ - const auto basePaths = fs::getDefaultPaths(fs::ImHexPath::Encodings); + const auto basePaths = paths::Encodings.read(); std::vector paths; for (const auto &path : basePaths) { std::error_code error; diff --git a/plugins/builtin/source/content/views/view_pattern_editor.cpp b/plugins/builtin/source/content/views/view_pattern_editor.cpp index 1c03fa78ce2e5..1820424fa108b 100644 --- a/plugins/builtin/source/content/views/view_pattern_editor.cpp +++ b/plugins/builtin/source/content/views/view_pattern_editor.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -239,9 +240,9 @@ namespace hex::plugin::builtin { if (ImGui::BeginPopup("##pattern_editor_context_menu")) { // no shortcut for this if (ImGui::MenuItem("hex.builtin.menu.file.import.pattern_file"_lang, nullptr, false)) - importPatternFile(); + m_importPatternFile(); if (ImGui::MenuItem("hex.builtin.menu.file.export.pattern_file"_lang, nullptr, false)) - exportPatternFile(); + m_exportPatternFile(); ImGui::Separator(); @@ -1413,7 +1414,7 @@ namespace hex::plugin::builtin { bool popupOpen = false; std::error_code errorCode; - for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Patterns)) { + for (const auto &dir : paths::Patterns.read()) { for (auto &entry : std::fs::recursive_directory_iterator(dir, errorCode)) { task.update(); @@ -1792,11 +1793,11 @@ namespace hex::plugin::builtin { void ViewPatternEditor::registerMenuItems() { /* Import Pattern */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.import", "hex.builtin.menu.file.import.pattern" }, ICON_VS_FILE_CODE, 4050, Shortcut::None, - importPatternFile, ImHexApi::Provider::isValid); + m_importPatternFile, ImHexApi::Provider::isValid); /* Export Pattern */ ContentRegistry::Interface::addMenuItem({ "hex.builtin.menu.file", "hex.builtin.menu.file.export", "hex.builtin.menu.file.export.pattern" }, ICON_VS_FILE_CODE, 7050, Shortcut::None, - exportPatternFile, [this] { + m_exportPatternFile, [this] { return !wolv::util::trim(m_textEditor.GetText()).empty() && ImHexApi::Provider::isValid(); } ); diff --git a/plugins/builtin/source/content/views/view_store.cpp b/plugins/builtin/source/content/views/view_store.cpp index 284d66d4ce494..87ab4ec442705 100644 --- a/plugins/builtin/source/content/views/view_store.cpp +++ b/plugins/builtin/source/content/views/view_store.cpp @@ -38,26 +38,26 @@ namespace hex::plugin::builtin { m_httpRequest.setTimeout(30'0000); - addCategory("hex.builtin.view.store.tab.patterns", "patterns", fs::ImHexPath::Patterns); - addCategory("hex.builtin.view.store.tab.includes", "includes", fs::ImHexPath::PatternsInclude); - addCategory("hex.builtin.view.store.tab.magic", "magic", fs::ImHexPath::Magic, []{ + addCategory("hex.builtin.view.store.tab.patterns", "patterns", &paths::Patterns); + addCategory("hex.builtin.view.store.tab.includes", "includes", &paths::PatternsInclude); + addCategory("hex.builtin.view.store.tab.magic", "magic", &paths::Magic, []{ magic::compile(); }); - addCategory("hex.builtin.view.store.tab.nodes", "nodes", fs::ImHexPath::Nodes); - addCategory("hex.builtin.view.store.tab.encodings", "encodings", fs::ImHexPath::Encodings); - addCategory("hex.builtin.view.store.tab.constants", "constants", fs::ImHexPath::Constants); - addCategory("hex.builtin.view.store.tab.themes", "themes", fs::ImHexPath::Themes, [this]{ + addCategory("hex.builtin.view.store.tab.nodes", "nodes", &paths::Nodes); + addCategory("hex.builtin.view.store.tab.encodings", "encodings", &paths::Encodings); + addCategory("hex.builtin.view.store.tab.constants", "constants", &paths::Constants); + addCategory("hex.builtin.view.store.tab.themes", "themes", &paths::Themes, [this]{ auto themeFile = wolv::io::File(m_downloadPath, wolv::io::File::Mode::Read); ThemeManager::addTheme(themeFile.readString()); }); - addCategory("hex.builtin.view.store.tab.yara", "yara", fs::ImHexPath::Yara); + addCategory("hex.builtin.view.store.tab.yara", "yara", &paths::Yara); } void updateEntryMetadata(StoreEntry &storeEntry, const StoreCategory &category) { // Check if file is installed already or has an update available - for (const auto &folder : fs::getDefaultPaths(category.path)) { + for (const auto &folder : category.path->write()) { auto path = folder / std::fs::path(storeEntry.fileName); if (wolv::io::fs::exists(path)) { @@ -296,9 +296,9 @@ namespace hex::plugin::builtin { this->drawStore(); } - bool ViewStore::download(fs::ImHexPath pathType, const std::string &fileName, const std::string &url) { + bool ViewStore::download(const paths::impl::DefaultPath *pathType, const std::string &fileName, const std::string &url) { bool downloading = false; - for (const auto &folderPath : fs::getDefaultPaths(pathType)) { + for (const auto &folderPath : pathType->write()) { if (!fs::isPathWritable(folderPath)) continue; @@ -327,9 +327,9 @@ namespace hex::plugin::builtin { return true; } - bool ViewStore::remove(fs::ImHexPath pathType, const std::string &fileName) { + bool ViewStore::remove(const paths::impl::DefaultPath *pathType, const std::string &fileName) { bool removed = true; - for (const auto &path : fs::getDefaultPaths(pathType)) { + for (const auto &path : pathType->write()) { const auto filePath = path / fileName; const auto folderPath = (path / std::fs::path(fileName).stem()); @@ -343,7 +343,7 @@ namespace hex::plugin::builtin { return removed; } - void ViewStore::addCategory(const UnlocalizedString &unlocalizedName, const std::string &requestName, fs::ImHexPath path, std::function downloadCallback) { + void ViewStore::addCategory(const UnlocalizedString &unlocalizedName, const std::string &requestName, const paths::impl::DefaultPath *path, std::function downloadCallback) { m_categories.push_back({ unlocalizedName, requestName, path, { }, std::move(downloadCallback) }); } diff --git a/plugins/builtin/source/content/welcome_screen.cpp b/plugins/builtin/source/content/welcome_screen.cpp index 919cfc8eecbbb..e43cb24ec1e13 100644 --- a/plugins/builtin/source/content/welcome_screen.cpp +++ b/plugins/builtin/source/content/welcome_screen.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -87,8 +88,8 @@ namespace hex::plugin::builtin { // Anonymize the log file { - for (u32 pathType = 0; pathType < u32(fs::ImHexPath::END); pathType++) { - for (auto &folder : fs::getDefaultPaths(static_cast(pathType))) { + for (const auto &paths : paths::All) { + for (auto &folder : paths->all()) { auto parent = wolv::util::toUTF8String(folder.parent_path()); data = wolv::util::replaceStrings(data, parent, "<*****>"); } @@ -546,7 +547,7 @@ namespace hex::plugin::builtin { constexpr static auto BackupFileName = "crash_backup.hexproj"; bool hasCrashed = false; - for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Config)) { + for (const auto &path : paths::Config.read()) { if (auto crashFilePath = std::fs::path(path) / CrashFileName; wolv::io::fs::exists(crashFilePath)) { hasCrashed = true; @@ -646,7 +647,7 @@ namespace hex::plugin::builtin { // Load info banner texture either locally or from the server TaskManager::doLater([] { - for (const auto &defaultPath : fs::getDefaultPaths(fs::ImHexPath::Resources)) { + for (const auto &defaultPath : paths::Resources.read()) { const auto infoBannerPath = defaultPath / "info_banner.png"; if (wolv::io::fs::exists(infoBannerPath)) { s_infoBannerTexture = ImGuiExt::Texture::fromImage(infoBannerPath, ImGuiExt::Texture::Filter::Linear); diff --git a/plugins/builtin/source/content/window_decoration.cpp b/plugins/builtin/source/content/window_decoration.cpp index 6756345e8231f..400171fac6cef 100644 --- a/plugins/builtin/source/content/window_decoration.cpp +++ b/plugins/builtin/source/content/window_decoration.cpp @@ -75,24 +75,29 @@ namespace hex::plugin::builtin { void drawSidebar(ImVec2 dockSpaceSize, ImVec2 sidebarPos, float sidebarWidth) { static i32 openWindow = -1; u32 index = 0; + u32 drawIndex = 0; ImGui::PushID("SideBarWindows"); for (const auto &[icon, callback, enabledCallback] : ContentRegistry::Interface::impl::getSidebarItems()) { - ImGui::SetCursorPosY(sidebarPos.y + sidebarWidth * index); + ImGui::SetCursorPosY(sidebarPos.y + sidebarWidth * drawIndex); ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetColorU32(ImGuiCol_MenuBarBg)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabActive)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabHovered)); - ImGui::BeginDisabled(!(ImHexApi::Provider::isValid() && enabledCallback())); - { - if (ImGui::Button(icon.c_str(), ImVec2(sidebarWidth, sidebarWidth))) { - if (static_cast(openWindow) == index) - openWindow = -1; - else - openWindow = index; + + if (enabledCallback()) { + drawIndex += 1; + ImGui::BeginDisabled(!ImHexApi::Provider::isValid()); + { + if (ImGui::Button(icon.c_str(), ImVec2(sidebarWidth, sidebarWidth))) { + if (static_cast(openWindow) == index) + openWindow = -1; + else + openWindow = index; + } } + ImGui::EndDisabled(); } - ImGui::EndDisabled(); ImGui::PopStyleColor(3); @@ -122,7 +127,7 @@ namespace hex::plugin::builtin { } ImGui::NewLine(); - index++; + index += 1; } ImGui::PopID(); } diff --git a/plugins/fonts/source/font_loader.cpp b/plugins/fonts/source/font_loader.cpp index 4c8057b7fd1f7..cf7b13c0282a1 100644 --- a/plugins/fonts/source/font_loader.cpp +++ b/plugins/fonts/source/font_loader.cpp @@ -7,13 +7,16 @@ #include #include + #include -#include #include #include +#include #include + #include +#include namespace hex::fonts { @@ -214,7 +217,7 @@ namespace hex::fonts { // If no custom font has been specified, search for a file called "font.ttf" in one of the resource folders if (fontFile.empty()) { - for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Resources)) { + for (const auto &dir : paths::Resources.read()) { auto path = dir / "font.ttf"; if (wolv::io::fs::exists(path)) { log::info("Loading custom font from {}", wolv::util::toUTF8String(path)); diff --git a/plugins/script_loader/source/loaders/dotnet/dotnet_loader.cpp b/plugins/script_loader/source/loaders/dotnet/dotnet_loader.cpp index 264a3d6894076..ce0200a4cee96 100644 --- a/plugins/script_loader/source/loaders/dotnet/dotnet_loader.cpp +++ b/plugins/script_loader/source/loaders/dotnet/dotnet_loader.cpp @@ -23,6 +23,8 @@ #include #include #include +#include + #include extern "C" void igSetCurrentContext(ImGuiContext* ctx); @@ -57,7 +59,7 @@ namespace hex::script::loader { auto netHostLibrary = loadLibrary("libnethost.so"); #elif defined(OS_MACOS) void *netHostLibrary = nullptr; - for (const auto &pluginPath : fs::getDefaultPaths(fs::ImHexPath::Plugins)) { + for (const auto &pluginPath : paths::Plugins.read()) { auto frameworksPath = pluginPath.parent_path().parent_path() / "Frameworks"; netHostLibrary = loadLibrary((frameworksPath / "libnethost.dylib").c_str()); @@ -65,7 +67,7 @@ namespace hex::script::loader { break; } if (netHostLibrary == nullptr) { - for (const auto &librariesPath : fs::getDefaultPaths(fs::ImHexPath::Libraries)) { + for (const auto &librariesPath : paths::Libraries.read()) { netHostLibrary = loadLibrary((librariesPath / "libnethost.dylib").c_str()); if (netHostLibrary != nullptr) break; @@ -165,7 +167,7 @@ namespace hex::script::loader { return false; } - for (const auto& path : hex::fs::getDefaultPaths(hex::fs::ImHexPath::Plugins)) { + for (const auto& path : paths::Plugins.read()) { auto assemblyLoader = path / "AssemblyLoader.dll"; if (!wolv::io::fs::exists(assemblyLoader)) continue; @@ -219,7 +221,7 @@ namespace hex::script::loader { bool DotNetLoader::loadAll() { this->clearScripts(); - for (const auto &imhexPath : hex::fs::getDefaultPaths(hex::fs::ImHexPath::Scripts)) { + for (const auto &imhexPath : paths::Scripts.read()) { auto directoryPath = imhexPath / "custom" / "dotnet"; if (!wolv::io::fs::exists(directoryPath)) wolv::io::fs::createDirectories(directoryPath); diff --git a/plugins/yara_rules/source/content/data_information_sections.cpp b/plugins/yara_rules/source/content/data_information_sections.cpp index 622812bfc1296..39f7c929c2de4 100644 --- a/plugins/yara_rules/source/content/data_information_sections.cpp +++ b/plugins/yara_rules/source/content/data_information_sections.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -25,7 +26,7 @@ namespace hex::plugin::yara { }; void process(Task &task, prv::Provider *provider, Region region) override { - for (const auto &yaraSignaturePath : fs::getDefaultPaths(fs::ImHexPath::YaraAdvancedAnalysis)) { + for (const auto &yaraSignaturePath : paths::YaraAdvancedAnalysis.read()) { for (const auto &ruleFilePath : std::fs::recursive_directory_iterator(yaraSignaturePath)) { wolv::io::File file(ruleFilePath.path(), wolv::io::File::Mode::Read); if (!file.isValid()) diff --git a/plugins/yara_rules/source/content/views/view_yara.cpp b/plugins/yara_rules/source/content/views/view_yara.cpp index 9c0c4f6422944..2d21ebfdb290d 100644 --- a/plugins/yara_rules/source/content/views/view_yara.cpp +++ b/plugins/yara_rules/source/content/views/view_yara.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -21,7 +22,7 @@ namespace hex::plugin::yara { YaraRule::init(); ContentRegistry::FileHandler::add({ ".yar", ".yara" }, [](const auto &path) { - for (const auto &destPath : fs::getDefaultPaths(fs::ImHexPath::Yara)) { + for (const auto &destPath : paths::Yara.write()) { if (wolv::io::fs::copyFile(path, destPath / path.filename(), std::fs::copy_options::overwrite_existing)) { ui::ToastInfo::open("hex.yara_rules.view.yara.rule_added"_lang); return true; @@ -143,7 +144,7 @@ namespace hex::plugin::yara { } if (ImGuiExt::IconButton(ICON_VS_ADD, ImGui::GetStyleColorVec4(ImGuiCol_Text))) { - const auto basePaths = fs::getDefaultPaths(fs::ImHexPath::Yara); + const auto basePaths = paths::Yara.read(); std::vector paths; for (const auto &path : basePaths) { std::error_code error;