diff --git a/Sofa/framework/Helper/src/sofa/helper/Utils.cpp b/Sofa/framework/Helper/src/sofa/helper/Utils.cpp index 9bb99fc101c..27158f42202 100644 --- a/Sofa/framework/Helper/src/sofa/helper/Utils.cpp +++ b/Sofa/framework/Helper/src/sofa/helper/Utils.cpp @@ -234,42 +234,28 @@ std::map Utils::readBasicIniFile(const std::string& pa } // no standard/portable way -const std::string& Utils::getUserLocalDirectory() +const std::string& Utils::getUserHomeDirectory() { - auto computeUserHomeDirectory = []() { -// Windows: "LocalAppData" directory i.e ${HOME}\AppData\Local -#ifdef WIN32 - std::wstring wresult; - wchar_t* path = nullptr; - const auto hr = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &path); - if (SUCCEEDED(hr)) - { - wresult = std::wstring(path); - } - if (path) - { - CoTaskMemFree(path); - } - - return Utils::narrowString(wresult); - +#ifdef WIN32 // Windows: ${HOME} + const char* homeDir = std::getenv("USERPROFILE"); + return std::string(homeDir); #elif defined(__APPLE__) // macOS : ${HOME}/Library/Application Support - // https://stackoverflow.com/questions/5123361/finding-library-application-support-from-c - + // https://stackoverflow.com/questions/5123361/finding-library-application-support-from-c + char path[PATH_MAX]; auto state = sysdir_start_search_path_enumeration(SYSDIR_DIRECTORY_APPLICATION_SUPPORT, SYSDIR_DOMAIN_MASK_USER); if ((state = sysdir_get_next_search_path_enumeration(state, path))) { glob_t globbuf; - if (glob(path, GLOB_TILDE, nullptr, &globbuf) == 0) + if (glob(path, GLOB_TILDE, nullptr, &globbuf) == 0) { std::string result(globbuf.gl_pathv[0]); globfree(&globbuf); return result; - } + } else { // "Unable to expand tilde" @@ -281,34 +267,76 @@ const std::string& Utils::getUserLocalDirectory() // "Failed to get settings folder" return std::string(""); } - + +#else // Linux: ${HOME} + + const char* homeDir; + + // if HOME is defined + if ((homeDir = std::getenv("HOME")) == nullptr) + { + // else system calls are used + homeDir = getpwuid(getuid())->pw_dir; + } + + return std::string(homeDir); + +#endif + }; + + static std::string homeDir = FileSystem::cleanPath(computeUserHomeDirectory()); + return homeDir; +} + +const std::string& Utils::getSofaDataDirectory() +{ + constexpr std::string_view sofaDataDirSuffix = "SOFAData"; + + static std::string sofaDataDirectory = FileSystem::cleanPath(FileSystem::findOrCreateAValidPath( + FileSystem::append(getUserHomeDirectory(), sofaDataDirSuffix))); + + return sofaDataDirectory; +} + + +// no standard/portable way +const std::string& Utils::getUserLocalDirectory() +{ + auto computeUserLocalDirectory = []() + { +#ifdef WIN32 // Windows: "LocalAppData" directory i.e ${HOME}\AppData\Local + std::wstring wresult; + wchar_t* path = nullptr; + const auto hr = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, nullptr, &path); + if (SUCCEEDED(hr)) + { + wresult = std::wstring(path); + } + if (path) + { + CoTaskMemFree(path); + } + + return Utils::narrowString(wresult); +#elif defined(__APPLE__) // macOS : ${HOME}/Library/Application Support + return getUserHomeDirectory(); #else // Linux: either ${XDG_CONFIG_HOME} if defined, or ${HOME}/.config (should be equivalent) const char* configDir; // if env.var XDG_CONFIG_HOME is defined if ((configDir = std::getenv("XDG_CONFIG_HOME")) == nullptr) { - const char* homeDir; - - // else if HOME is defined - if ((homeDir = std::getenv("HOME")) == nullptr) - { - // else system calls are used - homeDir = getpwuid(getuid())->pw_dir; - } - - return std::string(homeDir) + std::string("/.config"); + return getUserHomeDirectory() + std::string("/.config"); } else { return std::string(configDir); } - #endif }; - static std::string homeDir = FileSystem::cleanPath(computeUserHomeDirectory()); - return homeDir; + static std::string userLocalDir = FileSystem::cleanPath(computeUserLocalDirectory()); + return userLocalDir; } const std::string& Utils::getSofaUserLocalDirectory() diff --git a/Sofa/framework/Helper/src/sofa/helper/Utils.h b/Sofa/framework/Helper/src/sofa/helper/Utils.h index 388c09e5d40..816ce6051b3 100644 --- a/Sofa/framework/Helper/src/sofa/helper/Utils.h +++ b/Sofa/framework/Helper/src/sofa/helper/Utils.h @@ -75,6 +75,12 @@ static const std::string& getExecutablePath(); /// @brief Get the path to the directory of the executable that is currently running. static const std::string& getExecutableDirectory(); +/// @brief Get the path to the current user home directory. +static const std::string& getUserHomeDirectory(); + +/// @brief Get the path to the SOFA data directory into the current user home directory. +static const std::string& getSofaDataDirectory(); + /// @brief Get the path to the current user local config directory. static const std::string& getUserLocalDirectory(); diff --git a/applications/projects/runSofa/Main.cpp b/applications/projects/runSofa/Main.cpp index 6688d961f1e..5e272e43fd7 100644 --- a/applications/projects/runSofa/Main.cpp +++ b/applications/projects/runSofa/Main.cpp @@ -374,8 +374,8 @@ int main(int argc, char** argv) msg_info(appName) << "GuiDataRepository paths = " << GuiDataRepository.getPathsJoined(); // Initialise paths - BaseGUI::setConfigDirectoryPath(Utils::getSofaPathPrefix() + "/config", true); - BaseGUI::setScreenshotDirectoryPath(Utils::getSofaPathPrefix() + "/screenshots", true); + BaseGUI::setConfigDirectoryPath(Utils::getSofaUserLocalDirectory() + "/config", true); + BaseGUI::setScreenshotDirectoryPath(Utils::getSofaDataDirectory() + "/screenshots", true); // Add Batch GUI (runSofa without any GUIs won't be useful) sofa::gui::batch::init();