mirror of
https://github.com/WerWolv/ImHex.git
synced 2026-04-01 21:17:44 -05:00
sys: Refactor of filesystem functions. Fixed crashes where fs errors weren't caught correctly
Addresses the crash mentioned in #462
This commit is contained in:
@@ -113,7 +113,7 @@ set(LIBIMHEX_SOURCES
|
||||
source/data_processor/node.cpp
|
||||
|
||||
source/helpers/utils.cpp
|
||||
source/helpers/paths.cpp
|
||||
source/helpers/fs.cpp
|
||||
source/helpers/magic.cpp
|
||||
source/helpers/crypto.cpp
|
||||
source/helpers/net.cpp
|
||||
@@ -149,7 +149,7 @@ if (APPLE)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES} source/helpers/paths_mac.mm)
|
||||
set(LIBIMHEX_SOURCES ${LIBIMHEX_SOURCES} source/helpers/fs_macos.mm)
|
||||
endif ()
|
||||
|
||||
add_compile_definitions(IMHEX_PROJECT_NAME="${PROJECT_NAME}")
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <hex/pattern_language/token.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
@@ -372,7 +372,7 @@ namespace hex {
|
||||
|
||||
namespace impl {
|
||||
|
||||
using Callback = std::function<bool(fs::path)>;
|
||||
using Callback = std::function<bool(std::fs::path)>;
|
||||
struct Entry {
|
||||
std::vector<std::string> extensions;
|
||||
Callback callback;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <functional>
|
||||
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#define EVENT_DEF(event_name, ...) \
|
||||
struct event_name final : public hex::Event<__VA_ARGS__> { \
|
||||
@@ -101,7 +101,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
/* Default Events */
|
||||
EVENT_DEF(EventFileLoaded, fs::path);
|
||||
EVENT_DEF(EventFileLoaded, std::fs::path);
|
||||
EVENT_DEF(EventFileUnloaded);
|
||||
EVENT_DEF(EventDataChanged);
|
||||
EVENT_DEF(EventHighlightingChanged);
|
||||
@@ -124,7 +124,7 @@ namespace hex {
|
||||
EVENT_DEF(RequestSetPatternLanguageCode, std::string);
|
||||
EVENT_DEF(RequestChangeWindowTitle, std::string);
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
EVENT_DEF(RequestOpenFile, fs::path);
|
||||
EVENT_DEF(RequestOpenFile, std::fs::path);
|
||||
EVENT_DEF(RequestChangeTheme, u32);
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
EVENT_DEF(RequestCreateProvider, std::string, hex::prv::Provider **);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace hex {
|
||||
|
||||
class Plugin {
|
||||
public:
|
||||
explicit Plugin(const fs::path &path);
|
||||
explicit Plugin(const std::fs::path &path);
|
||||
Plugin(const Plugin &) = delete;
|
||||
Plugin(Plugin &&other) noexcept;
|
||||
~Plugin();
|
||||
@@ -26,7 +26,7 @@ namespace hex {
|
||||
void setImGuiContext(ImGuiContext *ctx) const;
|
||||
[[nodiscard]] bool isBuiltinPlugin() const;
|
||||
|
||||
[[nodiscard]] const fs::path &getPath() const;
|
||||
[[nodiscard]] const std::fs::path &getPath() const;
|
||||
|
||||
[[nodiscard]] bool isLoaded() const;
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace hex {
|
||||
using IsBuiltinPluginFunc = bool (*)();
|
||||
|
||||
void *m_handle = nullptr;
|
||||
fs::path m_path;
|
||||
std::fs::path m_path;
|
||||
|
||||
mutable bool m_initialized = false;
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace hex {
|
||||
public:
|
||||
PluginManager() = delete;
|
||||
|
||||
static bool load(const fs::path &pluginFolder);
|
||||
static bool load(const std::fs::path &pluginFolder);
|
||||
static void unload();
|
||||
static void reload();
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
private:
|
||||
static fs::path s_pluginFolder;
|
||||
static std::fs::path s_pluginFolder;
|
||||
static std::vector<Plugin> s_plugins;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,18 +6,19 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
class EncodingFile {
|
||||
public:
|
||||
enum class Type {
|
||||
enum class Type
|
||||
{
|
||||
Thingy
|
||||
};
|
||||
|
||||
EncodingFile() = default;
|
||||
EncodingFile(Type type, const fs::path &path);
|
||||
EncodingFile(Type type, const std::fs::path &path);
|
||||
|
||||
[[nodiscard]] std::pair<std::string_view, size_t> getEncodingFor(const std::vector<u8> &buffer) const;
|
||||
[[nodiscard]] size_t getLongestSequence() const { return this->m_longestSequence; }
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
#define off64_t off_t
|
||||
@@ -16,7 +16,7 @@
|
||||
#define ftruncate64 ftruncate
|
||||
#endif
|
||||
|
||||
namespace hex {
|
||||
namespace hex::fs {
|
||||
|
||||
class File {
|
||||
public:
|
||||
@@ -27,7 +27,7 @@ namespace hex {
|
||||
Create
|
||||
};
|
||||
|
||||
explicit File(const fs::path &path, Mode mode) noexcept;
|
||||
explicit File(const std::fs::path &path, Mode mode) noexcept;
|
||||
File() noexcept;
|
||||
File(const File &) = delete;
|
||||
File(File &&other) noexcept;
|
||||
@@ -38,7 +38,7 @@ namespace hex {
|
||||
|
||||
|
||||
[[nodiscard]] bool isValid() const {
|
||||
return this->m_file != nullptr && fs::exists(this->m_path) && !fs::is_directory(this->m_path);
|
||||
return this->m_file != nullptr && fs::exists(this->m_path) && !fs::isDirectory(this->m_path);
|
||||
}
|
||||
|
||||
void seek(u64 offset);
|
||||
@@ -59,13 +59,13 @@ namespace hex {
|
||||
bool remove();
|
||||
|
||||
auto getHandle() { return this->m_file; }
|
||||
const fs::path &getPath() { return this->m_path; }
|
||||
const std::fs::path &getPath() { return this->m_path; }
|
||||
|
||||
void disableBuffering();
|
||||
|
||||
private:
|
||||
FILE *m_file;
|
||||
fs::path m_path;
|
||||
std::fs::path m_path;
|
||||
};
|
||||
|
||||
}
|
||||
83
lib/libimhex/include/hex/helpers/fs.hpp
Normal file
83
lib/libimhex/include/hex/helpers/fs.hpp
Normal file
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
#include <nfd.hpp>
|
||||
|
||||
namespace std::fs {
|
||||
using namespace std::filesystem;
|
||||
}
|
||||
|
||||
namespace hex::fs {
|
||||
|
||||
static inline bool exists(const std::fs::path &path) {
|
||||
std::error_code error;
|
||||
return std::filesystem::exists(path, error) && !error;
|
||||
}
|
||||
|
||||
static inline bool createDirectories(const std::fs::path &path) {
|
||||
std::error_code error;
|
||||
return std::filesystem::create_directories(path, error) && !error;
|
||||
}
|
||||
|
||||
static inline bool isRegularFile(const std::fs::path &path) {
|
||||
std::error_code error;
|
||||
return std::filesystem::is_regular_file(path, error) && !error;
|
||||
}
|
||||
|
||||
static inline bool copyFile(const std::fs::path &from, const std::fs::path &to, std::fs::copy_options = std::fs::copy_options::none) {
|
||||
std::error_code error;
|
||||
return std::filesystem::copy_file(from, to, error) && !error;
|
||||
}
|
||||
|
||||
static inline bool isDirectory(const std::fs::path &path) {
|
||||
std::error_code error;
|
||||
return std::filesystem::is_directory(path, error) && !error;
|
||||
}
|
||||
|
||||
static inline bool remove(const std::fs::path &path) {
|
||||
std::error_code error;
|
||||
return std::filesystem::remove(path, error) && !error;
|
||||
}
|
||||
|
||||
static inline uintmax_t getFileSize(const std::fs::path &path) {
|
||||
std::error_code error;
|
||||
auto size = std::filesystem::file_size(path, error);
|
||||
|
||||
if (error) return 0;
|
||||
else return size;
|
||||
}
|
||||
|
||||
bool isPathWritable(std::fs::path path);
|
||||
|
||||
enum class DialogMode
|
||||
{
|
||||
Open,
|
||||
Save,
|
||||
Folder
|
||||
};
|
||||
|
||||
bool openFileBrowser(const std::string &title, DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback, const std::string &defaultPath = {});
|
||||
|
||||
enum class ImHexPath
|
||||
{
|
||||
Patterns,
|
||||
PatternsInclude,
|
||||
Magic,
|
||||
Python,
|
||||
Plugins,
|
||||
Yara,
|
||||
Config,
|
||||
Resources,
|
||||
Constants,
|
||||
Encodings,
|
||||
Logs
|
||||
};
|
||||
|
||||
std::string getExecutablePath();
|
||||
|
||||
std::vector<std::fs::path> getDefaultPaths(ImHexPath path, bool listNonExisting = false);
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
struct _object;
|
||||
typedef struct _object PyObject;
|
||||
@@ -18,13 +18,13 @@ namespace hex {
|
||||
public:
|
||||
LoaderScript() = delete;
|
||||
|
||||
static bool processFile(const fs::path &scriptPath);
|
||||
static bool processFile(const std::fs::path &scriptPath);
|
||||
|
||||
static void setFilePath(const fs::path &filePath) { LoaderScript::s_filePath = filePath; }
|
||||
static void setFilePath(const std::fs::path &filePath) { LoaderScript::s_filePath = filePath; }
|
||||
static void setDataProvider(prv::Provider *provider) { LoaderScript::s_dataProvider = provider; }
|
||||
|
||||
private:
|
||||
static inline fs::path s_filePath;
|
||||
static inline std::fs::path s_filePath;
|
||||
static inline prv::Provider *s_dataProvider;
|
||||
|
||||
static PyObject *Py_getFilePath(PyObject *self, PyObject *args);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <curl/system.h>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
using CURL = void;
|
||||
struct curl_slist;
|
||||
@@ -40,8 +40,8 @@ namespace hex {
|
||||
std::future<Response<std::string>> getString(const std::string &url, u32 timeout = DefaultTimeout);
|
||||
std::future<Response<nlohmann::json>> getJson(const std::string &url, u32 timeout = DefaultTimeout);
|
||||
|
||||
std::future<Response<std::string>> uploadFile(const std::string &url, const fs::path &filePath, u32 timeout = DefaultTimeout);
|
||||
std::future<Response<void>> downloadFile(const std::string &url, const fs::path &filePath, u32 timeout = DefaultTimeout);
|
||||
std::future<Response<std::string>> uploadFile(const std::string &url, const std::fs::path &filePath, u32 timeout = DefaultTimeout);
|
||||
std::future<Response<void>> downloadFile(const std::string &url, const std::fs::path &filePath, u32 timeout = DefaultTimeout);
|
||||
|
||||
[[nodiscard]] std::string encode(const std::string &input);
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
namespace hex {
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
enum class ImHexPath {
|
||||
Patterns,
|
||||
PatternsInclude,
|
||||
Magic,
|
||||
Python,
|
||||
Plugins,
|
||||
Yara,
|
||||
Config,
|
||||
Resources,
|
||||
Constants,
|
||||
Encodings,
|
||||
Logs
|
||||
};
|
||||
|
||||
std::string getExecutablePath();
|
||||
|
||||
std::vector<fs::path> getPath(ImHexPath path, bool listNonExisting = false);
|
||||
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/event.hpp>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
@@ -16,8 +16,8 @@ namespace hex {
|
||||
public:
|
||||
ProjectFile() = delete;
|
||||
|
||||
static bool load(const fs::path &filePath);
|
||||
static bool store(fs::path filePath = {});
|
||||
static bool load(const std::fs::path &filePath);
|
||||
static bool store(std::fs::path filePath = {});
|
||||
|
||||
[[nodiscard]] static bool hasUnsavedChanges() {
|
||||
return ProjectFile::s_hasUnsavedChanged;
|
||||
@@ -29,10 +29,10 @@ namespace hex {
|
||||
ProjectFile::s_hasUnsavedChanged = true;
|
||||
|
||||
if (setWindowTitle)
|
||||
EventManager::post<RequestChangeWindowTitle>(fs::path(getFilePath()).filename().string());
|
||||
EventManager::post<RequestChangeWindowTitle>(std::fs::path(getFilePath()).filename().string());
|
||||
}
|
||||
|
||||
[[nodiscard]] static const fs::path &getProjectFilePath() {
|
||||
[[nodiscard]] static const std::fs::path &getProjectFilePath() {
|
||||
return ProjectFile::s_currProjectFilePath;
|
||||
}
|
||||
|
||||
@@ -41,11 +41,11 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
[[nodiscard]] static const fs::path &getFilePath() {
|
||||
[[nodiscard]] static const std::fs::path &getFilePath() {
|
||||
return ProjectFile::s_filePath;
|
||||
}
|
||||
|
||||
static void setFilePath(const fs::path &filePath) {
|
||||
static void setFilePath(const std::fs::path &filePath) {
|
||||
ProjectFile::s_filePath = filePath;
|
||||
|
||||
EventManager::post<RequestChangeWindowTitle>(filePath.filename().string());
|
||||
@@ -92,10 +92,10 @@ namespace hex {
|
||||
}
|
||||
|
||||
private:
|
||||
static fs::path s_currProjectFilePath;
|
||||
static std::fs::path s_currProjectFilePath;
|
||||
static bool s_hasUnsavedChanged;
|
||||
|
||||
static fs::path s_filePath;
|
||||
static std::fs::path s_filePath;
|
||||
static std::string s_pattern;
|
||||
static Patches s_patches;
|
||||
static std::list<ImHexApi::Bookmarks::Entry> s_bookmarks;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <hex.hpp>
|
||||
|
||||
#include <hex/helpers/concepts.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <bit>
|
||||
@@ -18,8 +18,6 @@
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include <nfd.hpp>
|
||||
|
||||
#define TOKEN_CONCAT_IMPL(x, y) x##y
|
||||
#define TOKEN_CONCAT(x, y) TOKEN_CONCAT_IMPL(x, y)
|
||||
#define ANONYMOUS_VARIABLE(prefix) TOKEN_CONCAT(prefix, __COUNTER__)
|
||||
@@ -44,8 +42,6 @@ namespace hex {
|
||||
std::string encodeByteString(const std::vector<u8> &bytes);
|
||||
std::vector<u8> decodeByteString(const std::string &string);
|
||||
|
||||
bool isPathWritable(fs::path path);
|
||||
|
||||
[[nodiscard]] constexpr inline u64 extract(u8 from, u8 to, const hex::unsigned_integral auto &value) {
|
||||
if (from < to) std::swap(from, to);
|
||||
|
||||
@@ -268,15 +264,6 @@ namespace hex {
|
||||
trimRight(s);
|
||||
}
|
||||
|
||||
enum class DialogMode
|
||||
{
|
||||
Open,
|
||||
Save,
|
||||
Folder
|
||||
};
|
||||
|
||||
bool openFileBrowser(const std::string &title, DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(fs::path)> &callback, const std::string &defaultPath = {});
|
||||
|
||||
float float16ToFloat32(u16 float16);
|
||||
|
||||
inline bool equalsIgnoreCase(const std::string &left, const std::string &right) {
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace hex::pl {
|
||||
|
||||
[[nodiscard]] std::optional<std::vector<std::shared_ptr<ASTNode>>> parseString(const std::string &code);
|
||||
[[nodiscard]] bool executeString(prv::Provider *provider, const std::string &string, const std::map<std::string, Token::Literal> &envVars = {}, const std::map<std::string, Token::Literal> &inVariables = {}, bool checkResult = true);
|
||||
[[nodiscard]] bool executeFile(prv::Provider *provider, const fs::path &path, const std::map<std::string, Token::Literal> &envVars = {}, const std::map<std::string, Token::Literal> &inVariables = {});
|
||||
[[nodiscard]] bool executeFile(prv::Provider *provider, const std::fs::path &path, const std::map<std::string, Token::Literal> &envVars = {}, const std::map<std::string, Token::Literal> &inVariables = {});
|
||||
[[nodiscard]] std::pair<bool, std::optional<Token::Literal>> executeFunction(prv::Provider *provider, const std::string &code);
|
||||
[[nodiscard]] const std::vector<std::shared_ptr<ASTNode>> &getCurrentAST() const;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <hex/pattern_language/error.hpp>
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace hex::pl {
|
||||
std::set<std::tuple<std::string, std::string, u32>> m_defines;
|
||||
std::set<std::tuple<std::string, std::string, u32>> m_pragmas;
|
||||
|
||||
std::set<fs::path> m_onceIncludedFiles;
|
||||
std::set<std::fs::path> m_onceIncludedFiles;
|
||||
|
||||
std::optional<PatternLanguageError> m_error;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include <hex/providers/overlay.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
namespace hex::pl {
|
||||
class PatternLanguage;
|
||||
@@ -37,7 +37,7 @@ namespace hex::prv {
|
||||
virtual void insert(u64 offset, size_t size);
|
||||
|
||||
virtual void save();
|
||||
virtual void saveAs(const fs::path &path);
|
||||
virtual void saveAs(const std::fs::path &path);
|
||||
|
||||
virtual void readRaw(u64 offset, void *buffer, size_t size) = 0;
|
||||
virtual void writeRaw(u64 offset, const void *buffer, size_t size) = 0;
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace hex {
|
||||
static void showFatalPopup(const std::string &errorMessage);
|
||||
static void showYesNoQuestionPopup(const std::string &message, const std::function<void()> &yesCallback, const std::function<void()> &noCallback);
|
||||
|
||||
static void showFileChooserPopup(const std::vector<fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(fs::path)> &callback);
|
||||
static void showFileChooserPopup(const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback);
|
||||
|
||||
[[nodiscard]] virtual bool hasViewMenuItemEntry() const;
|
||||
[[nodiscard]] virtual ImVec2 getMinSize() const;
|
||||
@@ -76,8 +76,8 @@ namespace hex {
|
||||
static std::function<void()> s_yesCallback, s_noCallback;
|
||||
|
||||
static u32 s_selectableFileIndex;
|
||||
static std::vector<fs::path> s_selectableFiles;
|
||||
static std::function<void(fs::path)> s_selectableFileOpenCallback;
|
||||
static std::vector<std::fs::path> s_selectableFiles;
|
||||
static std::function<void(std::fs::path)> s_selectableFileOpenCallback;
|
||||
static std::vector<nfdfilteritem_t> s_selectableFilesValidExtensions;
|
||||
|
||||
static ImFontAtlas *s_fontAtlas;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <hex/ui/view.hpp>
|
||||
@@ -16,7 +16,7 @@ namespace hex {
|
||||
|
||||
void load() {
|
||||
bool loaded = false;
|
||||
for (const auto &dir : hex::getPath(ImHexPath::Config)) {
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
|
||||
std::ifstream settingsFile(dir / "settings.json");
|
||||
|
||||
if (settingsFile.good()) {
|
||||
@@ -31,7 +31,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
void store() {
|
||||
for (const auto &dir : hex::getPath(ImHexPath::Config)) {
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Config)) {
|
||||
std::ofstream settingsFile(dir / "settings.json", std::ios::trunc);
|
||||
|
||||
if (settingsFile.good()) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
Plugin::Plugin(const fs::path &path) : m_path(path) {
|
||||
Plugin::Plugin(const std::fs::path &path) : m_path(path) {
|
||||
this->m_handle = dlopen(path.string().c_str(), RTLD_LAZY);
|
||||
|
||||
if (this->m_handle == nullptr) {
|
||||
@@ -15,7 +15,7 @@ namespace hex {
|
||||
return;
|
||||
}
|
||||
|
||||
auto pluginName = fs::path(path).stem().string();
|
||||
auto pluginName = std::fs::path(path).stem().string();
|
||||
|
||||
this->m_initializePluginFunction = getPluginFunction<InitializePluginFunc>("initializePlugin");
|
||||
this->m_getPluginNameFunction = getPluginFunction<GetPluginNameFunc>("getPluginName");
|
||||
@@ -110,7 +110,7 @@ namespace hex {
|
||||
return false;
|
||||
}
|
||||
|
||||
const fs::path &Plugin::getPath() const {
|
||||
const std::fs::path &Plugin::getPath() const {
|
||||
return this->m_path;
|
||||
}
|
||||
|
||||
@@ -124,16 +124,16 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
fs::path PluginManager::s_pluginFolder;
|
||||
std::fs::path PluginManager::s_pluginFolder;
|
||||
std::vector<Plugin> PluginManager::s_plugins;
|
||||
|
||||
bool PluginManager::load(const fs::path &pluginFolder) {
|
||||
bool PluginManager::load(const std::fs::path &pluginFolder) {
|
||||
if (!fs::exists(pluginFolder))
|
||||
return false;
|
||||
|
||||
PluginManager::s_pluginFolder = pluginFolder;
|
||||
|
||||
for (auto &pluginPath : fs::directory_iterator(pluginFolder)) {
|
||||
for (auto &pluginPath : std::fs::directory_iterator(pluginFolder)) {
|
||||
if (pluginPath.is_regular_file() && pluginPath.path().extension() == ".hexplug")
|
||||
PluginManager::s_plugins.emplace_back(pluginPath.path().string());
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
namespace hex {
|
||||
|
||||
EncodingFile::EncodingFile(Type type, const fs::path &path) {
|
||||
EncodingFile::EncodingFile(Type type, const std::fs::path &path) {
|
||||
std::ifstream encodingFile(path.c_str());
|
||||
|
||||
switch (type) {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::fs {
|
||||
|
||||
File::File(const fs::path &path, Mode mode) noexcept : m_path(path) {
|
||||
File::File(const std::fs::path &path, Mode mode) noexcept : m_path(path) {
|
||||
if (mode == File::Mode::Read)
|
||||
this->m_file = fopen64(path.string().c_str(), "rb");
|
||||
else if (mode == File::Mode::Write)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/helpers/paths_mac.h>
|
||||
#include <hex/helpers/fs_macos.h>
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
#include <xdg.hpp>
|
||||
|
||||
@@ -14,7 +15,7 @@
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
|
||||
namespace hex {
|
||||
namespace hex::fs {
|
||||
|
||||
std::string getExecutablePath() {
|
||||
#if defined(OS_WINDOWS)
|
||||
@@ -34,8 +35,57 @@ namespace hex {
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<fs::path> getPath(ImHexPath path, bool listNonExisting) {
|
||||
std::vector<fs::path> result;
|
||||
|
||||
bool isPathWritable(std::fs::path path) {
|
||||
constexpr static auto TestFileName = "__imhex__tmp__";
|
||||
{
|
||||
File file(path / TestFileName, File::Mode::Read);
|
||||
if (file.isValid()) {
|
||||
if (!file.remove())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
File file(path / TestFileName, File::Mode::Create);
|
||||
bool result = file.isValid();
|
||||
if (!file.remove())
|
||||
return false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool openFileBrowser(const std::string &title, DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback, const std::string &defaultPath) {
|
||||
NFD::Init();
|
||||
|
||||
nfdchar_t *outPath;
|
||||
nfdresult_t result;
|
||||
switch (mode) {
|
||||
case DialogMode::Open:
|
||||
result = NFD::OpenDialog(outPath, validExtensions.data(), validExtensions.size(), defaultPath.c_str());
|
||||
break;
|
||||
case DialogMode::Save:
|
||||
result = NFD::SaveDialog(outPath, validExtensions.data(), validExtensions.size(), defaultPath.c_str());
|
||||
break;
|
||||
case DialogMode::Folder:
|
||||
result = NFD::PickFolder(outPath, defaultPath.c_str());
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
if (result == NFD_OKAY) {
|
||||
callback(reinterpret_cast<const char8_t *>(outPath));
|
||||
NFD::FreePath(outPath);
|
||||
}
|
||||
|
||||
NFD::Quit();
|
||||
|
||||
return result == NFD_OKAY;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::fs::path> getDefaultPaths(ImHexPath path, bool listNonExisting) {
|
||||
std::vector<std::fs::path> result;
|
||||
const auto exePath = getExecutablePath();
|
||||
const std::string settingName { "hex.builtin.setting.folders" };
|
||||
auto userDirs = ContentRegistry::Settings::read(settingName, settingName, std::vector<std::string> {});
|
||||
@@ -47,9 +97,9 @@ namespace hex {
|
||||
};
|
||||
|
||||
#if defined(OS_WINDOWS)
|
||||
const auto parentDir = fs::path(exePath).parent_path();
|
||||
const auto parentDir = std::fs::path(exePath).parent_path();
|
||||
|
||||
fs::path appDataDir;
|
||||
std::fs::path appDataDir;
|
||||
{
|
||||
LPWSTR wAppDataPath = nullptr;
|
||||
if (!SUCCEEDED(SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &wAppDataPath)))
|
||||
@@ -59,7 +109,7 @@ namespace hex {
|
||||
CoTaskMemFree(wAppDataPath);
|
||||
}
|
||||
|
||||
std::vector<fs::path> paths = { appDataDir / "imhex", parentDir };
|
||||
std::vector<std::fs::path> paths = { appDataDir / "imhex", parentDir };
|
||||
|
||||
switch (path) {
|
||||
case ImHexPath::Patterns:
|
||||
@@ -126,9 +176,9 @@ namespace hex {
|
||||
}
|
||||
#elif defined(OS_MACOS)
|
||||
// Get path to special directories
|
||||
const fs::path applicationSupportDir(getMacApplicationSupportDirectoryPath());
|
||||
const std::fs::path applicationSupportDir(getMacApplicationSupportDirectoryPath());
|
||||
|
||||
std::vector<fs::path> paths = { applicationSupportDir, exePath };
|
||||
std::vector<std::fs::path> paths = { applicationSupportDir, exePath };
|
||||
|
||||
switch (path) {
|
||||
case ImHexPath::Patterns:
|
||||
@@ -170,8 +220,8 @@ namespace hex {
|
||||
__builtin_unreachable();
|
||||
}
|
||||
#else
|
||||
std::vector<fs::path> configDirs = xdg::ConfigDirs();
|
||||
std::vector<fs::path> dataDirs = xdg::DataDirs();
|
||||
std::vector<std::fs::path> configDirs = xdg::ConfigDirs();
|
||||
std::vector<std::fs::path> dataDirs = xdg::DataDirs();
|
||||
|
||||
configDirs.push_back(xdg::ConfigHomeDir());
|
||||
dataDirs.push_back(xdg::DataHomeDir());
|
||||
@@ -231,7 +281,7 @@ namespace hex {
|
||||
|
||||
if (!listNonExisting) {
|
||||
result.erase(std::remove_if(result.begin(), result.end(), [](const auto &path) {
|
||||
return !fs::is_directory(path);
|
||||
return !fs::isDirectory(path);
|
||||
}),
|
||||
result.end());
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <hex/helpers/loader_script_handler.hpp>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <hex/providers/provider.hpp>
|
||||
@@ -178,11 +178,11 @@ namespace hex {
|
||||
return createStructureType("union", args);
|
||||
}
|
||||
|
||||
bool LoaderScript::processFile(const fs::path &scriptPath) {
|
||||
bool LoaderScript::processFile(const std::fs::path &scriptPath) {
|
||||
Py_SetProgramName(Py_DecodeLocale("ImHex", nullptr));
|
||||
|
||||
for (const auto &dir : hex::getPath(ImHexPath::Python)) {
|
||||
if (fs::exists(fs::path(dir / "lib" / "python" PYTHON_VERSION_MAJOR_MINOR))) {
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Python)) {
|
||||
if (fs::exists(std::fs::path(dir / "lib" / "python" PYTHON_VERSION_MAJOR_MINOR))) {
|
||||
Py_SetPythonHome(Py_DecodeLocale(dir.string().c_str(), nullptr));
|
||||
break;
|
||||
}
|
||||
@@ -218,7 +218,7 @@ namespace hex {
|
||||
PyList_Insert(sysPath, 0, path);
|
||||
}
|
||||
|
||||
File scriptFile(scriptPath, File::Mode::Read);
|
||||
fs::File scriptFile(scriptPath, fs::File::Mode::Read);
|
||||
PyRun_SimpleFile(scriptFile.getHandle(), scriptFile.getPath().string().c_str());
|
||||
|
||||
Py_Finalize();
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace hex::log {
|
||||
|
||||
static File g_loggerFile;
|
||||
static fs::File g_loggerFile;
|
||||
|
||||
FILE *getDestination() {
|
||||
if (g_loggerFile.isValid())
|
||||
@@ -23,9 +23,9 @@ namespace hex::log {
|
||||
void redirectToFile() {
|
||||
if (g_loggerFile.isValid()) return;
|
||||
|
||||
for (const auto &path : hex::getPath(ImHexPath::Logs, true)) {
|
||||
fs::create_directories(path);
|
||||
g_loggerFile = File(path / hex::format("{0:%Y%m%d_%H%M%S}.log", fmt::localtime(std::chrono::system_clock::now())), File::Mode::Create);
|
||||
for (const auto &path : fs::getDefaultPaths(fs::ImHexPath::Logs, true)) {
|
||||
fs::createDirectories(path);
|
||||
g_loggerFile = fs::File(path / hex::format("{0:%Y%m%d_%H%M%S}.log", fmt::localtime(std::chrono::system_clock::now())), fs::File::Mode::Create);
|
||||
g_loggerFile.disableBuffering();
|
||||
|
||||
if (g_loggerFile.isValid()) break;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <hex/helpers/magic.hpp>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <hex/providers/provider.hpp>
|
||||
|
||||
@@ -24,8 +24,8 @@ namespace hex::magic {
|
||||
std::string magicFiles;
|
||||
|
||||
std::error_code error;
|
||||
for (const auto &dir : hex::getPath(ImHexPath::Magic)) {
|
||||
for (const auto &entry : fs::directory_iterator(dir, error)) {
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::Magic)) {
|
||||
for (const auto &entry : std::fs::directory_iterator(dir, error)) {
|
||||
if (entry.is_regular_file() && ((sourceFiles && entry.path().extension().empty()) || (!sourceFiles && entry.path().extension() == ".mgc")))
|
||||
magicFiles += entry.path().string() + MAGIC_PATH_SEPARATOR;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
std::future<Response<std::string>> Net::uploadFile(const std::string &url, const fs::path &filePath, u32 timeout) {
|
||||
std::future<Response<std::string>> Net::uploadFile(const std::string &url, const std::fs::path &filePath, u32 timeout) {
|
||||
this->m_transmissionActive.lock();
|
||||
|
||||
return std::async(std::launch::async, [=, this] {
|
||||
@@ -179,7 +179,7 @@ namespace hex {
|
||||
|
||||
ON_SCOPE_EXIT { this->m_transmissionActive.unlock(); };
|
||||
|
||||
File file(filePath.string(), File::Mode::Read);
|
||||
fs::File file(filePath.string(), fs::File::Mode::Read);
|
||||
if (!file.isValid())
|
||||
return Response<std::string> { 400, {} };
|
||||
|
||||
@@ -209,7 +209,7 @@ namespace hex {
|
||||
});
|
||||
}
|
||||
|
||||
std::future<Response<void>> Net::downloadFile(const std::string &url, const fs::path &filePath, u32 timeout) {
|
||||
std::future<Response<void>> Net::downloadFile(const std::string &url, const std::fs::path &filePath, u32 timeout) {
|
||||
this->m_transmissionActive.lock();
|
||||
|
||||
return std::async(std::launch::async, [=, this] {
|
||||
@@ -217,7 +217,7 @@ namespace hex {
|
||||
|
||||
ON_SCOPE_EXIT { this->m_transmissionActive.unlock(); };
|
||||
|
||||
File file(filePath.string(), File::Mode::Create);
|
||||
fs::File file(filePath.string(), fs::File::Mode::Create);
|
||||
if (!file.isValid())
|
||||
return Response<void> { 400 };
|
||||
|
||||
|
||||
@@ -9,10 +9,10 @@ using json = nlohmann::json;
|
||||
|
||||
namespace hex {
|
||||
|
||||
fs::path ProjectFile::s_currProjectFilePath;
|
||||
std::fs::path ProjectFile::s_currProjectFilePath;
|
||||
bool ProjectFile::s_hasUnsavedChanged = false;
|
||||
|
||||
fs::path ProjectFile::s_filePath;
|
||||
std::fs::path ProjectFile::s_filePath;
|
||||
std::string ProjectFile::s_pattern;
|
||||
Patches ProjectFile::s_patches;
|
||||
std::list<ImHexApi::Bookmarks::Entry> ProjectFile::s_bookmarks;
|
||||
@@ -46,7 +46,7 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
bool ProjectFile::load(const fs::path &filePath) {
|
||||
bool ProjectFile::load(const std::fs::path &filePath) {
|
||||
ProjectFile::s_hasUnsavedChanged = false;
|
||||
|
||||
json projectFileData;
|
||||
@@ -55,7 +55,7 @@ namespace hex {
|
||||
std::ifstream projectFile(filePath.c_str());
|
||||
projectFile >> projectFileData;
|
||||
|
||||
ProjectFile::s_filePath = fs::path(projectFileData["filePath"].get<std::string>());
|
||||
ProjectFile::s_filePath = std::fs::path(projectFileData["filePath"].get<std::string>());
|
||||
ProjectFile::s_pattern = projectFileData["pattern"];
|
||||
ProjectFile::s_patches = projectFileData["patches"].get<Patches>();
|
||||
ProjectFile::s_dataProcessorContent = projectFileData["dataProcessor"];
|
||||
@@ -80,7 +80,7 @@ namespace hex {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProjectFile::store(fs::path filePath) {
|
||||
bool ProjectFile::store(std::fs::path filePath) {
|
||||
EventManager::post<EventProjectFileStore>();
|
||||
|
||||
json projectFileData;
|
||||
|
||||
@@ -394,53 +394,6 @@ namespace hex {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool isPathWritable(fs::path path) {
|
||||
constexpr static auto TestFileName = "__imhex__tmp__";
|
||||
{
|
||||
File file(path / TestFileName, File::Mode::Read);
|
||||
if (file.isValid()) {
|
||||
if (!file.remove())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
File file(path / TestFileName, File::Mode::Create);
|
||||
bool result = file.isValid();
|
||||
if (!file.remove())
|
||||
return false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool openFileBrowser(const std::string &title, DialogMode mode, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(fs::path)> &callback, const std::string &defaultPath) {
|
||||
NFD::Init();
|
||||
|
||||
nfdchar_t *outPath;
|
||||
nfdresult_t result;
|
||||
switch (mode) {
|
||||
case DialogMode::Open:
|
||||
result = NFD::OpenDialog(outPath, validExtensions.data(), validExtensions.size(), defaultPath.c_str());
|
||||
break;
|
||||
case DialogMode::Save:
|
||||
result = NFD::SaveDialog(outPath, validExtensions.data(), validExtensions.size(), defaultPath.c_str());
|
||||
break;
|
||||
case DialogMode::Folder:
|
||||
result = NFD::PickFolder(outPath, defaultPath.c_str());
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
if (result == NFD_OKAY) {
|
||||
callback(reinterpret_cast<const char8_t *>(outPath));
|
||||
NFD::FreePath(outPath);
|
||||
}
|
||||
|
||||
NFD::Quit();
|
||||
|
||||
return result == NFD_OKAY;
|
||||
}
|
||||
|
||||
float float16ToFloat32(u16 float16) {
|
||||
u32 sign = float16 >> 15;
|
||||
u32 exponent = (float16 >> 10) & 0x1F;
|
||||
|
||||
@@ -184,8 +184,8 @@ namespace hex::pl {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PatternLanguage::executeFile(prv::Provider *provider, const fs::path &path, const std::map<std::string, Token::Literal> &envVars, const std::map<std::string, Token::Literal> &inVariables) {
|
||||
File file(path, File::Mode::Read);
|
||||
bool PatternLanguage::executeFile(prv::Provider *provider, const std::fs::path &path, const std::map<std::string, Token::Literal> &envVars, const std::map<std::string, Token::Literal> &inVariables) {
|
||||
fs::File file(path, fs::File::Mode::Read);
|
||||
|
||||
return this->executeString(provider, file.readString(), envVars, inVariables, true);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include <hex/pattern_language/preprocessor.hpp>
|
||||
|
||||
#include <hex/helpers/fmt.hpp>
|
||||
#include <hex/helpers/paths.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
@@ -59,26 +59,26 @@ namespace hex::pl {
|
||||
}
|
||||
offset += 1;
|
||||
|
||||
fs::path includePath = includeFile;
|
||||
std::fs::path includePath = includeFile;
|
||||
|
||||
if (includeFile[0] != '/') {
|
||||
for (const auto &dir : hex::getPath(ImHexPath::PatternsInclude)) {
|
||||
fs::path tempPath = dir / includePath;
|
||||
if (fs::is_regular_file(tempPath)) {
|
||||
for (const auto &dir : fs::getDefaultPaths(fs::ImHexPath::PatternsInclude)) {
|
||||
std::fs::path tempPath = dir / includePath;
|
||||
if (fs::isRegularFile(tempPath)) {
|
||||
includePath = tempPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!fs::is_regular_file(includePath)) {
|
||||
if (!fs::isRegularFile(includePath)) {
|
||||
if (includePath.parent_path().filename().string() == "std")
|
||||
throwPreprocessorError(hex::format("{0}: No such file.\n\nThis file might be part of the standard library.\nYou can install the standard library though\nthe Content Store found under Help -> Content Store.", includeFile.c_str()), lineNumber);
|
||||
else
|
||||
throwPreprocessorError(hex::format("{0}: No such file", includeFile.c_str()), lineNumber);
|
||||
}
|
||||
|
||||
File file(includePath, File::Mode::Read);
|
||||
fs::File file(includePath, fs::File::Mode::Read);
|
||||
if (!file.isValid()) {
|
||||
throwPreprocessorError(hex::format("{0}: Failed to open file", includeFile.c_str()), lineNumber);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace hex::prv {
|
||||
}
|
||||
|
||||
void Provider::save() { }
|
||||
void Provider::saveAs(const fs::path &path) { }
|
||||
void Provider::saveAs(const std::fs::path &path) { }
|
||||
|
||||
void Provider::resize(size_t newSize) { }
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ namespace hex {
|
||||
std::function<void()> View::s_yesCallback, View::s_noCallback;
|
||||
|
||||
u32 View::s_selectableFileIndex;
|
||||
std::vector<fs::path> View::s_selectableFiles;
|
||||
std::function<void(fs::path)> View::s_selectableFileOpenCallback;
|
||||
std::vector<std::fs::path> View::s_selectableFiles;
|
||||
std::function<void(std::fs::path)> View::s_selectableFileOpenCallback;
|
||||
std::vector<nfdfilteritem_t> View::s_selectableFilesValidExtensions;
|
||||
|
||||
ImFontAtlas *View::s_fontAtlas;
|
||||
@@ -108,7 +108,7 @@ namespace hex {
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("hex.builtin.common.browse"_lang)) {
|
||||
hex::openFileBrowser("hex.builtin.common.open"_lang, DialogMode::Open, View::s_selectableFilesValidExtensions, [](const auto &path) {
|
||||
fs::openFileBrowser("hex.builtin.common.open"_lang, fs::DialogMode::Open, View::s_selectableFilesValidExtensions, [](const auto &path) {
|
||||
View::s_selectableFileOpenCallback(path);
|
||||
ImGui::CloseCurrentPopup();
|
||||
});
|
||||
@@ -145,9 +145,9 @@ namespace hex {
|
||||
ImHexApi::Tasks::doLater([] { ImGui::OpenPopup("hex.builtin.common.question"_lang); });
|
||||
}
|
||||
|
||||
void View::showFileChooserPopup(const std::vector<fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(fs::path)> &callback) {
|
||||
void View::showFileChooserPopup(const std::vector<std::fs::path> &paths, const std::vector<nfdfilteritem_t> &validExtensions, const std::function<void(std::fs::path)> &callback) {
|
||||
if (paths.empty()) {
|
||||
hex::openFileBrowser("hex.builtin.common.open"_lang, DialogMode::Open, validExtensions, [callback](const auto &path) {
|
||||
fs::openFileBrowser("hex.builtin.common.open"_lang, fs::DialogMode::Open, validExtensions, [callback](const auto &path) {
|
||||
callback(path);
|
||||
});
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user