| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #include <fmt/format.h> |
| | #include <utility> |
| | #include <QDir> |
| | #include <QProcessEnvironment> |
| | #include <QStandardPaths> |
| | #include <QCoreApplication> |
| |
|
| | #include "ApplicationDirectories.h" |
| |
|
| | #include <FCConfig.h> |
| |
|
| | #if defined(FC_OS_LINUX) || defined(FC_OS_MACOSX) || defined(FC_OS_BSD) |
| | #include <pwd.h> |
| | #endif |
| |
|
| | #include <Base/FileInfo.h> |
| | #include <Base/Exception.h> |
| | #include "SafeMode.h" |
| |
|
| | #include <Python.h> |
| | #include <QString> |
| |
|
| | #include "Base/Console.h" |
| |
|
| |
|
| | using namespace App; |
| | namespace fs = std::filesystem; |
| |
|
| | fs::path qstringToPath(const QString& path) |
| | { |
| | #if defined(FC_OS_WIN32) |
| | return {path.toStdWString()}; |
| | #else |
| | return {path.toStdString()}; |
| | #endif |
| | } |
| |
|
| | ApplicationDirectories::ApplicationDirectories(std::map<std::string,std::string> &config) |
| | { |
| | _currentVersion = extractVersionFromConfigMap(config); |
| | configurePaths(config); |
| | configureResourceDirectory(config); |
| | configureLibraryDirectory(config); |
| | configureHelpDirectory(config); |
| | } |
| |
|
| | const fs::path& ApplicationDirectories::getHomePath() const |
| | { |
| | return this->_home; |
| | } |
| |
|
| | const fs::path& ApplicationDirectories::getUserHomePath() const |
| | { |
| | return this->_userHome; |
| | } |
| |
|
| | const fs::path& ApplicationDirectories::getTempPath() const { |
| | return this->_temp; |
| | } |
| |
|
| | fs::path ApplicationDirectories::getTempFileName(const std::string & filename) const { |
| | auto tempPath = Base::FileInfo::pathToString(getTempPath()); |
| | if (filename.empty()) { |
| | return Base::FileInfo::getTempFileName(nullptr, tempPath.c_str()); |
| | } |
| | return Base::FileInfo::getTempFileName(filename.c_str(), tempPath.c_str()); |
| | } |
| |
|
| | const fs::path& ApplicationDirectories::getUserCachePath() const |
| | { |
| | return this->_userCache; |
| | } |
| |
|
| | const fs::path& ApplicationDirectories::getUserAppDataDir() const |
| | { |
| | return this->_userAppData; |
| | } |
| |
|
| | const fs::path& ApplicationDirectories::getUserMacroDir() const |
| | { |
| | return this->_userMacro; |
| | } |
| |
|
| | const fs::path& ApplicationDirectories::getResourceDir() const |
| | { |
| | return this->_resource; |
| | } |
| |
|
| | const fs::path& ApplicationDirectories::getHelpDir() const |
| | { |
| | return this->_help; |
| | } |
| |
|
| | const fs::path& ApplicationDirectories::getUserConfigPath() const { |
| | return this->_userConfig; |
| | } |
| |
|
| | const fs::path& ApplicationDirectories::getLibraryDir() const { |
| | return this->_library; |
| | } |
| |
|
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | fs::path ApplicationDirectories::findPath(const fs::path& stdHome, const fs::path& customHome, |
| | const std::vector<std::string>& subdirs, bool create) { |
| | fs::path appData = customHome; |
| | if (appData.empty()) { |
| | appData = stdHome; |
| | } |
| |
|
| | |
| | if (customHome.empty()) { |
| | for (const auto& it : subdirs) { |
| | appData = appData / it; |
| | } |
| | } |
| |
|
| | |
| | if (create && !fs::exists(appData) && !Py_IsInitialized()) { |
| | try { |
| | fs::create_directories(appData); |
| | } catch (const fs::filesystem_error& e) { |
| | throw Base::FileSystemError("Could not create directories. Failed with: " + e.code().message()); |
| | } |
| | } |
| |
|
| | return appData; |
| | } |
| |
|
| | void ApplicationDirectories::appendVersionIfPossible(const fs::path& basePath, std::vector<std::string> &subdirs) const |
| | { |
| | fs::path pathToCheck = basePath; |
| | for (const auto& it : subdirs) { |
| | pathToCheck = pathToCheck / it; |
| | } |
| | if (isVersionedPath(pathToCheck)) { |
| | return; |
| | } |
| | if (fs::exists(pathToCheck)) { |
| | std::string version = mostRecentAvailableConfigVersion(pathToCheck); |
| | if (!version.empty()) { |
| | subdirs.emplace_back(std::move(version)); |
| | } |
| | } else { |
| | auto [major, minor] = _currentVersion; |
| | subdirs.emplace_back(versionStringForPath(major, minor)); |
| | } |
| | } |
| |
|
| | void ApplicationDirectories::configurePaths(std::map<std::string,std::string>& mConfig) |
| | { |
| | bool keepDeprecatedPaths = mConfig.contains("KeepDeprecatedPaths"); |
| |
|
| | |
| | _home = fs::path(mConfig.at("AppHomePath")); |
| | mConfig["BinPath"] = mConfig.at("AppHomePath") + "bin" + PATHSEP; |
| | mConfig["DocPath"] = mConfig.at("AppHomePath") + "doc" + PATHSEP; |
| |
|
| | |
| | auto [customHome, customData, customTemp] = getCustomPaths(); |
| | _usingCustomDirectories = !customHome.empty() || !customData.empty(); |
| |
|
| | |
| | auto [configHome, dataHome, cacheHome, tempPath] = getStandardPaths(); |
| |
|
| | if (mConfig.contains("SafeMode")) { |
| | if (startSafeMode(mConfig)) { |
| | |
| | |
| | return; |
| | } |
| | } |
| |
|
| | |
| | |
| | fs::path homePath = findUserHomePath(customHome); |
| | mConfig["UserHomePath"] = Base::FileInfo::pathToString(homePath); |
| | _userHome = homePath; |
| |
|
| | |
| | std::vector<std::string> subdirs; |
| | if (keepDeprecatedPaths) { |
| | configHome = homePath; |
| | dataHome = homePath; |
| | cacheHome = homePath; |
| | getOldDataLocation(mConfig, subdirs); |
| | } |
| | else { |
| | getSubDirectories(mConfig, subdirs); |
| | } |
| |
|
| |
|
| | |
| | |
| | auto dataSubdirs = subdirs; |
| | appendVersionIfPossible(dataHome, dataSubdirs); |
| | fs::path data = findPath(dataHome, customData, dataSubdirs, true); |
| | _userAppData = data; |
| | mConfig["UserAppData"] = Base::FileInfo::pathToString(data) + PATHSEP; |
| |
|
| |
|
| | |
| | |
| | auto configSubdirs = subdirs; |
| | appendVersionIfPossible(configHome, configSubdirs); |
| | fs::path config = findPath(configHome, customHome, configSubdirs, true); |
| | _userConfig = config; |
| | mConfig["UserConfigPath"] = Base::FileInfo::pathToString(config) + PATHSEP; |
| |
|
| |
|
| | |
| | |
| | std::vector<std::string> cachedirs = subdirs; |
| | cachedirs.emplace_back("Cache"); |
| | fs::path cache = findPath(cacheHome, customTemp, cachedirs, true); |
| | _userCache = cache; |
| | mConfig["UserCachePath"] = Base::FileInfo::pathToString(cache) + PATHSEP; |
| |
|
| |
|
| | |
| | |
| | std::vector<std::string> empty; |
| | fs::path tmp = findPath(tempPath, customTemp, empty, true); |
| | _temp = tmp; |
| | mConfig["AppTempPath"] = Base::FileInfo::pathToString(tmp) + PATHSEP; |
| |
|
| |
|
| | |
| | |
| | std::vector<std::string> macrodirs{"Macro"}; |
| | fs::path macro = findPath(_userAppData, customData, macrodirs, true); |
| | _userMacro = macro; |
| | mConfig["UserMacroPath"] = Base::FileInfo::pathToString(macro) + PATHSEP; |
| | } |
| |
|
| | bool ApplicationDirectories::startSafeMode(std::map<std::string,std::string>& mConfig) |
| | { |
| | SafeMode::StartSafeMode(); |
| | if (SafeMode::SafeModeEnabled()) { |
| | _userAppData = mConfig["UserAppData"]; |
| | _userConfig = mConfig["UserConfigPath"]; |
| | _userCache = mConfig["UserCachePath"]; |
| | _temp = mConfig["AppTempPath"]; |
| | _userMacro = mConfig["UserMacroPath"]; |
| | _userHome = mConfig["UserHomePath"]; |
| | _usingCustomDirectories = true; |
| | return true; |
| | } |
| | return false; |
| | } |
| |
|
| | std::filesystem::path ApplicationDirectories::sanitizePath(const std::string& pathAsString) |
| | { |
| | size_t positionOfFirstNull = pathAsString.find('\0'); |
| | if (positionOfFirstNull != std::string::npos) { |
| | return {pathAsString.substr(0, positionOfFirstNull)}; |
| | } |
| | return {pathAsString}; |
| | } |
| |
|
| | void ApplicationDirectories::configureResourceDirectory(const std::map<std::string,std::string>& mConfig) { |
| | #ifdef RESOURCEDIR |
| | |
| | fs::path path = sanitizePath(RESOURCEDIR); |
| | if (path.is_absolute()) { |
| | _resource = path; |
| | } else { |
| | _resource = Base::FileInfo::stringToPath(mConfig.at("AppHomePath")) / path; |
| | } |
| | #else |
| | _resource = fs::path(mConfig.at("AppHomePath")); |
| | #endif |
| | } |
| |
|
| | void ApplicationDirectories::configureLibraryDirectory(const std::map<std::string,std::string>& mConfig) { |
| | #ifdef LIBRARYDIR |
| | |
| | fs::path path = sanitizePath(LIBRARYDIR); |
| | if (path.is_absolute()) { |
| | _library = path; |
| | } else { |
| | _library = Base::FileInfo::stringToPath(mConfig.at("AppHomePath")) / path; |
| | } |
| | #else |
| | _library = Base::FileInfo::stringToPath(mConfig.at("AppHomePath")) / "lib"; |
| | #endif |
| | } |
| |
|
| |
|
| | void ApplicationDirectories::configureHelpDirectory(const std::map<std::string,std::string>& mConfig) |
| | { |
| | #ifdef DOCDIR |
| | |
| | fs::path path = sanitizePath(DOCDIR); |
| | if (path.is_absolute()) { |
| | _help = path; |
| | } else { |
| | _help = Base::FileInfo::stringToPath(mConfig.at("AppHomePath")) / path; |
| | } |
| | #else |
| | _help = Base::FileInfo::stringToPath(mConfig.at("DocPath")); |
| | #endif |
| | } |
| |
|
| |
|
| | fs::path ApplicationDirectories::getUserHome() |
| | { |
| | fs::path path; |
| | #if defined(FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_BSD) || defined(FC_OS_MACOSX) |
| | |
| | struct passwd pwd {}; |
| | struct passwd *result {}; |
| | constexpr std::size_t bufferLength = 16384; |
| | std::vector<char> buffer(bufferLength); |
| | const int error = getpwuid_r(getuid(), &pwd, buffer.data(), buffer.size(), &result); |
| | if (!result || error != 0) { |
| | throw Base::RuntimeError("Getting HOME path from system failed!"); |
| | } |
| | std::string sanitizedPath = sanitizePath(pwd.pw_dir); |
| | path = Base::FileInfo::stringToPath(sanitizedPath); |
| | #else |
| | path = Base::FileInfo::stringToPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString()); |
| | #endif |
| | return path; |
| | } |
| |
|
| | bool ApplicationDirectories::usingCustomDirectories() const |
| | { |
| | return _usingCustomDirectories; |
| | } |
| |
|
| | #if defined(FC_OS_WIN32) |
| | #include <codecvt> |
| | #include "ShlObj.h" |
| | QString ApplicationDirectories::getOldGenericDataLocation() |
| | { |
| | WCHAR szPath[MAX_PATH]; |
| | std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; |
| | if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, szPath))) { |
| | return QString::fromStdString(converter.to_bytes(szPath)); |
| | } |
| | return {}; |
| | } |
| | #endif |
| |
|
| | void ApplicationDirectories::getSubDirectories(const std::map<std::string,std::string>& mConfig, |
| | std::vector<std::string>& appData) |
| | { |
| | |
| | |
| | if (!mConfig.contains("AppDataSkipVendor") && mConfig.contains("ExeVendor")) { |
| | appData.push_back(mConfig.at("ExeVendor")); |
| | } |
| | appData.push_back(mConfig.at("ExeName")); |
| | } |
| |
|
| | void ApplicationDirectories::getOldDataLocation(const std::map<std::string,std::string>& mConfig, |
| | std::vector<std::string>& appData) |
| | { |
| | |
| | |
| | #if defined(FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_BSD) |
| | |
| | |
| | if (!mConfig.contains("AppDataSkipVendor")) { |
| | appData.push_back(std::string(".") + mConfig.at("ExeVendor")); |
| | appData.push_back(mConfig.at("ExeName")); |
| | } else { |
| | appData.push_back(std::string(".") + mConfig.at("ExeName")); |
| | } |
| |
|
| | #elif defined(FC_OS_MACOSX) || defined(FC_OS_WIN32) |
| | getSubDirectories(mConfig, appData); |
| | #endif |
| | } |
| |
|
| | fs::path ApplicationDirectories::findUserHomePath(const fs::path& userHome) |
| | { |
| | return userHome.empty() ? getUserHome() : userHome; |
| | } |
| |
|
| | std::tuple<fs::path, fs::path, fs::path> ApplicationDirectories::getCustomPaths() |
| | { |
| | const QProcessEnvironment env(QProcessEnvironment::systemEnvironment()); |
| | QString userHome = env.value(QStringLiteral("FREECAD_USER_HOME")); |
| | QString userData = env.value(QStringLiteral("FREECAD_USER_DATA")); |
| | QString userTemp = env.value(QStringLiteral("FREECAD_USER_TEMP")); |
| |
|
| | auto toNativePath = [](QString& path) { |
| | if (!path.isEmpty()) { |
| | if (const QDir dir(path); dir.exists()) { |
| | path = QDir::toNativeSeparators(dir.canonicalPath()); |
| | } |
| | else { |
| | path.clear(); |
| | } |
| | } |
| | }; |
| |
|
| | |
| | toNativePath(userHome); |
| | toNativePath(userData); |
| | toNativePath(userTemp); |
| |
|
| | |
| | if (!userHome.isEmpty() && userData.isEmpty()) { |
| | userData = userHome; |
| | } |
| |
|
| | |
| | if (!userHome.isEmpty() && userTemp.isEmpty()) { |
| | const QDir dir(userHome); |
| | dir.mkdir(QStringLiteral("temp")); |
| | const QFileInfo fi(dir, QStringLiteral("temp")); |
| | userTemp = fi.absoluteFilePath(); |
| | } |
| |
|
| | return {qstringToPath(userHome), |
| | qstringToPath(userData), |
| | qstringToPath(userTemp)}; |
| | } |
| |
|
| | std::tuple<fs::path, fs::path, fs::path, fs::path> ApplicationDirectories::getStandardPaths() |
| | { |
| | QString configHome = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation); |
| | QString dataHome = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); |
| | QString cacheHome = QStandardPaths::writableLocation(QStandardPaths::GenericCacheLocation); |
| | QString tempPath = QStandardPaths::writableLocation(QStandardPaths::TempLocation); |
| |
|
| | |
| | #if defined(FC_OS_WIN32) |
| | configHome = getOldGenericDataLocation(); |
| | dataHome = configHome; |
| |
|
| | |
| | |
| | |
| | |
| | #if (BOOST_VERSION < 107600) |
| | tempPath = QString::fromStdString(Base::FileInfo::getTempPath()); |
| | cacheHome = tempPath; |
| | #endif |
| | #endif |
| |
|
| | return {qstringToPath(configHome), |
| | qstringToPath(dataHome), |
| | qstringToPath(cacheHome), |
| | qstringToPath(tempPath)}; |
| | } |
| |
|
| |
|
| |
|
| | std::string ApplicationDirectories::versionStringForPath(int major, int minor) |
| | { |
| | |
| | |
| | return fmt::format("v{}-{}", major, minor); |
| | } |
| |
|
| | bool ApplicationDirectories::isVersionedPath(const fs::path &startingPath) const { |
| | for (int major = std::get<0>(_currentVersion); major >= 1; --major) { |
| | constexpr int largestPossibleMinor = 99; |
| | int startingMinor = largestPossibleMinor; |
| | if (major == std::get<0>(_currentVersion)) { |
| | startingMinor = std::get<1>(_currentVersion); |
| | } |
| | for (int minor = startingMinor; minor >= 0; --minor) { |
| | if (startingPath.filename() == versionStringForPath(major, minor)) { |
| | return true; |
| | } |
| | } |
| | } |
| | return false; |
| | } |
| |
|
| | std::string ApplicationDirectories::mostRecentAvailableConfigVersion(const fs::path &startingPath) const { |
| | for (int major = std::get<0>(_currentVersion); major >= 1; --major) { |
| | constexpr int largestPossibleMinor = 99; |
| | int startingMinor = largestPossibleMinor; |
| | if (major == std::get<0>(_currentVersion)) { |
| | startingMinor = std::get<1>(_currentVersion); |
| | } |
| | for (int minor = startingMinor; minor >= 0; --minor) { |
| | auto version = startingPath / versionStringForPath(major, minor); |
| | if (fs::is_directory(version)) { |
| | return versionStringForPath(major, minor); |
| | } |
| | } |
| | } |
| | return ""; |
| | } |
| |
|
| | fs::path ApplicationDirectories::mostRecentConfigFromBase(const fs::path &startingPath) const { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | |
| | auto current = startingPath / versionStringForPath(std::get<0>(_currentVersion), std::get<1>(_currentVersion)); |
| | if (fs::is_directory(current)) { |
| | return current; |
| | } |
| |
|
| | |
| | std::string bestVersion = mostRecentAvailableConfigVersion(startingPath); |
| | if (!bestVersion.empty()) { |
| | return startingPath / bestVersion; |
| | } |
| | return startingPath; |
| | } |
| |
|
| | bool ApplicationDirectories::usingCurrentVersionConfig(fs::path config) const { |
| | if (config.filename().empty()) { |
| | config = config.parent_path(); |
| | } |
| | auto version = Base::FileInfo::pathToString(config.filename()); |
| | return version == versionStringForPath(std::get<0>(_currentVersion), std::get<1>(_currentVersion)); |
| | } |
| |
|
| | void ApplicationDirectories::migrateConfig(const fs::path &oldPath, const fs::path &newPath) |
| | { |
| | fs::create_directories(newPath); |
| | for (auto& file : fs::directory_iterator(oldPath)) { |
| | if (file == newPath) { |
| | |
| | continue; |
| | } |
| | fs::copy(file.path(), |
| | newPath / file.path().filename(), |
| | fs::copy_options::recursive | fs::copy_options::copy_symlinks); |
| | } |
| | } |
| |
|
| | void ApplicationDirectories::migrateAllPaths(const std::vector<fs::path> &paths) const { |
| | auto [major, minor] = _currentVersion; |
| | std::set<fs::path> uniquePaths (paths.begin(), paths.end()); |
| | for (auto path : uniquePaths) { |
| | if (path.filename().empty()) { |
| | |
| | path = path.parent_path(); |
| | } |
| | fs::path newPath; |
| | if (isVersionedPath(path)) { |
| | newPath = path.parent_path() / versionStringForPath(major, minor); |
| | } else { |
| | newPath = path / versionStringForPath(major, minor); |
| | } |
| | Base::Console().message("Migrating config from %s to %s\n", Base::FileInfo::pathToString(path), Base::FileInfo::pathToString(newPath)); |
| | if (fs::exists(newPath)) { |
| | continue; |
| | } |
| | fs::create_directories(newPath); |
| | migrateConfig(path, newPath); |
| | } |
| | } |
| |
|
| | |
| | #if defined(__OpenBSD__) |
| | #include <cstdio> |
| | #include <cstdlib> |
| | #include <sys/param.h> |
| | #include <QCoreApplication> |
| |
|
| | fs::path ApplicationDirectories::findHomePath(const char* sCall) |
| | { |
| | |
| | |
| | |
| | std::string absPath; |
| | std::string homePath; |
| | if (Py_IsInitialized()) { |
| | |
| | |
| | |
| | |
| | char resolved[PATH_MAX]; |
| | char* path = realpath(sCall, resolved); |
| | if (path) |
| | absPath = path; |
| | } |
| | else { |
| | int argc = 1; |
| | QCoreApplication app(argc, (char**)(&sCall)); |
| | absPath = QCoreApplication::applicationFilePath().toStdString(); |
| | } |
| |
|
| | |
| | std::string::size_type pos = absPath.find_last_of("/"); |
| | homePath.assign(absPath,0,pos); |
| | pos = homePath.find_last_of("/"); |
| | homePath.assign(homePath,0,pos+1); |
| |
|
| | return Base::FileInfo::stringToPath(homePath); |
| | } |
| |
|
| | #elif defined (FC_OS_LINUX) || defined(FC_OS_CYGWIN) || defined(FC_OS_BSD) |
| | #include <cstdio> |
| | #include <cstdlib> |
| | #include <sys/param.h> |
| | #if defined(__FreeBSD__) |
| | #include <sys/sysctl.h> |
| | #endif |
| |
|
| | fs::path ApplicationDirectories::findHomePath(const char* sCall) |
| | { |
| | |
| | |
| | |
| | std::string absPath; |
| | std::string homePath; |
| | if (Py_IsInitialized()) { |
| | |
| | |
| | |
| | |
| | char resolved[PATH_MAX]; |
| | char* path = realpath(sCall, resolved); |
| | if (path) |
| | absPath = path; |
| | } |
| | else { |
| | |
| | |
| | |
| | |
| | |
| | char resolved[PATH_MAX]; |
| | #if defined(FC_OS_BSD) |
| | int mib[4]; |
| | mib[0] = CTL_KERN; |
| | mib[1] = KERN_PROC; |
| | mib[2] = KERN_PROC_PATHNAME; |
| | mib[3] = -1; |
| | size_t cb = sizeof(resolved); |
| | sysctl(mib, 4, resolved, &cb, NULL, 0); |
| | int nchars = strlen(resolved); |
| | #else |
| | int nchars = readlink("/proc/self/exe", resolved, PATH_MAX); |
| | #endif |
| | if (nchars < 0 || nchars >= PATH_MAX) |
| | throw Base::FileSystemError("Cannot determine the absolute path of the executable"); |
| | resolved[nchars] = '\0'; |
| | absPath = resolved; |
| | } |
| |
|
| | |
| | std::string::size_type pos = absPath.find_last_of("/"); |
| | homePath.assign(absPath,0,pos); |
| | pos = homePath.find_last_of("/"); |
| | homePath.assign(homePath,0,pos+1); |
| |
|
| | return Base::FileInfo::stringToPath(homePath); |
| | } |
| |
|
| | #elif defined(FC_OS_MACOSX) |
| | #include <mach-o/dyld.h> |
| | #include <string> |
| | #include <cstdlib> |
| | #include <sys/param.h> |
| |
|
| | fs::path ApplicationDirectories::findHomePath(const char* sCall) |
| | { |
| | |
| | |
| | |
| | if (!Py_IsInitialized()) { |
| | uint32_t sz = 0; |
| |
|
| | |
| | _NSGetExecutablePath(nullptr, &sz); |
| |
|
| | if (const auto buf = new char[++sz]; _NSGetExecutablePath(buf, &sz) == 0) { |
| | std::array<char, PATH_MAX> resolved{}; |
| | const char* path = realpath(buf, resolved.data()); |
| | delete [] buf; |
| |
|
| | if (path) { |
| | const std::string Call(resolved.data()); |
| | std::string TempHomePath; |
| | std::string::size_type pos = Call.find_last_of(fs::path::preferred_separator); |
| | TempHomePath.assign(Call,0,pos); |
| | pos = TempHomePath.find_last_of(fs::path::preferred_separator); |
| | TempHomePath.assign(TempHomePath,0,pos+1); |
| | return Base::FileInfo::stringToPath(TempHomePath); |
| | } |
| | } else { |
| | delete [] buf; |
| | } |
| | } |
| |
|
| | return Base::FileInfo::stringToPath(sCall); |
| | } |
| |
|
| | #elif defined (FC_OS_WIN32) |
| | fs::path ApplicationDirectories::findHomePath(const char* sCall) |
| | { |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | wchar_t szFileName [MAX_PATH]; |
| | QString dll(QString::fromUtf8(sCall)); |
| | if (Py_IsInitialized() || dll.endsWith(QLatin1String(".dll"))) { |
| | GetModuleFileNameW(GetModuleHandleA(sCall),szFileName, MAX_PATH-1); |
| | } |
| | else { |
| | GetModuleFileNameW(0, szFileName, MAX_PATH-1); |
| | } |
| |
|
| | std::wstring Call(szFileName), homePath; |
| | std::wstring::size_type pos = Call.find_last_of(fs::path::preferred_separator); |
| | homePath.assign(Call,0,pos); |
| | pos = homePath.find_last_of(fs::path::preferred_separator); |
| | homePath.assign(homePath,0,pos+1); |
| |
|
| | |
| | std::wstring binPath = homePath; |
| | binPath += L"bin"; |
| | SetDllDirectoryW(binPath.c_str()); |
| |
|
| | |
| | #ifdef _MSC_VER |
| | QString str = QString::fromUtf16(reinterpret_cast<const ushort *>(homePath.c_str())); |
| | #else |
| | QString str = QString::fromStdWString(homePath); |
| | #endif |
| | return qstringToPath(str); |
| | } |
| |
|
| | #else |
| | # error "std::string ApplicationDirectories::findHomePath(const char*) not implemented" |
| | #endif |
| |
|
| | std::tuple<int, int> ApplicationDirectories::extractVersionFromConfigMap(const std::map<std::string,std::string> &config) |
| | { |
| | try { |
| | int major = std::stoi(config.at("BuildVersionMajor")); |
| | int minor = std::stoi(config.at("BuildVersionMinor")); |
| | return std::make_tuple(major, minor); |
| | } catch (const std::exception& e) { |
| | throw Base::RuntimeError("Failed to parse version from config: " + std::string(e.what())); |
| | } |
| | } |
| |
|