diff --git a/samples/blackmiscsim/samplesp3d.cpp b/samples/blackmiscsim/samplesp3d.cpp index 9ec2f1f92..e2f2b6d57 100644 --- a/samples/blackmiscsim/samplesp3d.cpp +++ b/samples/blackmiscsim/samplesp3d.cpp @@ -10,7 +10,7 @@ //! \ingroup sampleblackmiscsim #include "samplesp3d.h" -#include "blackmisc/simulation/fscommon/fscommonutil.h" +#include "blackmisc/simulation/fscommon/fsdirectories.h" #include "blackmisc/stringutils.h" #include @@ -20,15 +20,15 @@ namespace BlackSample { void CSamplesP3D::samplesMisc(QTextStream &streamOut) { - QSet configFiles = CFsCommonUtil::findP3dAddOnConfigFiles("v5"); - if (configFiles.isEmpty()) { configFiles = CFsCommonUtil::findP3dAddOnConfigFiles("v4"); } + QSet configFiles = CFsDirectories::findP3dAddOnConfigFiles("v5"); + if (configFiles.isEmpty()) { configFiles = CFsDirectories::findP3dAddOnConfigFiles("v4"); } streamOut << BlackMisc::joinStringSet(configFiles, ", ") << Qt::endl; - const QSet addOnPaths = CFsCommonUtil::allConfigFilesPathValues(configFiles.values(), false, {}); + const QSet addOnPaths = CFsDirectories::allConfigFilesPathValues(configFiles.values(), false, {}); streamOut << BlackMisc::joinStringSet(addOnPaths, ", ") << Qt::endl; - const QSet simObjectPaths = CFsCommonUtil::fsxSimObjectsPaths("B:/fsx.cfg", false); + const QSet simObjectPaths = CFsDirectories::fsxSimObjectsPaths("B:/fsx.cfg", false); streamOut << BlackMisc::joinStringSet(simObjectPaths, ", ") << Qt::endl; } } // namespace diff --git a/src/blackgui/components/configsimulatorcomponent.cpp b/src/blackgui/components/configsimulatorcomponent.cpp index 356bc0b44..6c44d3e73 100644 --- a/src/blackgui/components/configsimulatorcomponent.cpp +++ b/src/blackgui/components/configsimulatorcomponent.cpp @@ -9,7 +9,7 @@ #include "configsimulatorcomponent.h" #include "blackgui/guiutility.h" #include "blackmisc/logmessage.h" -#include "blackmisc/simulation/fscommon/fscommonutil.h" +#include "blackmisc/simulation/fscommon/fsdirectories.h" #include "blackconfig/buildconfig.h" #include "ui_configsimulatorcomponent.h" @@ -61,9 +61,9 @@ namespace BlackGui } // no x64 check as we would allow to config 32bit with launcher x64 and vice versa - const bool p3d = (sims.isP3D() || !CFsCommonUtil::p3dDir().isEmpty()) && CBuildConfig::isCompiledWithP3DSupport(); - const bool fsx = (sims.isFSX() || !CFsCommonUtil::fsxDir().isEmpty()) && CBuildConfig::isCompiledWithFsxSupport(); - const bool fs9 = (sims.isFS9() || !CFsCommonUtil::fs9Dir().isEmpty()) && CBuildConfig::isCompiledWithFs9Support(); + const bool p3d = (sims.isP3D() || !CFsDirectories::p3dDir().isEmpty()) && CBuildConfig::isCompiledWithP3DSupport(); + const bool fsx = (sims.isFSX() || !CFsDirectories::fsxDir().isEmpty()) && CBuildConfig::isCompiledWithFsxSupport(); + const bool fs9 = (sims.isFS9() || !CFsDirectories::fs9Dir().isEmpty()) && CBuildConfig::isCompiledWithFs9Support(); const bool xp = sims.isXPlane() && CBuildConfig::isCompiledWithXPlaneSupport(); const bool fg = sims.isFG() && CBuildConfig::isCompiledWithFGSupport(); diff --git a/src/blackmisc/simulation/fscommon/aircraftcfgparser.cpp b/src/blackmisc/simulation/fscommon/aircraftcfgparser.cpp index ada9a18c8..417e0d041 100644 --- a/src/blackmisc/simulation/fscommon/aircraftcfgparser.cpp +++ b/src/blackmisc/simulation/fscommon/aircraftcfgparser.cpp @@ -8,7 +8,7 @@ #include "blackmisc/simulation/fscommon/aircraftcfgentries.h" #include "blackmisc/simulation/fscommon/aircraftcfgparser.h" -#include "blackmisc/simulation/fscommon/fscommonutil.h" +#include "blackmisc/simulation/fscommon/fsdirectories.h" #include "blackmisc/fileutils.h" #include "blackmisc/logmessage.h" #include "blackmisc/statusmessagelist.h" @@ -176,7 +176,7 @@ namespace BlackMisc // the sim.cfg/aircraft.cfg file should have an *.air file sibling // if not we assume these files can be ignored - const QDir dirForAir(directory, CFsCommonUtil::airFileFilter(), QDir::Name, QDir::Files | QDir::NoDotAndDotDot); + const QDir dirForAir(directory, CFsDirectories::airFileFilter(), QDir::Name, QDir::Files | QDir::NoDotAndDotDot); const int airFilesCount = dirForAir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::DirsLast).size(); const bool hasAirFiles = airFilesCount > 0; diff --git a/src/blackmisc/simulation/fscommon/fscommonutil.cpp b/src/blackmisc/simulation/fscommon/fscommonutil.cpp index 3b9924187..fbb739190 100644 --- a/src/blackmisc/simulation/fscommon/fscommonutil.cpp +++ b/src/blackmisc/simulation/fscommon/fscommonutil.cpp @@ -6,8 +6,9 @@ * or distributed except according to the terms contained in the LICENSE file. */ -#include "fscommonutil.h" -#include "aircraftcfgparser.h" +#include "blackmisc/simulation/fscommon/fscommonutil.h" +#include "blackmisc/simulation/fscommon/fsdirectories.h" +#include "blackmisc/simulation/fscommon/aircraftcfgparser.h" #include "blackmisc/swiftdirectories.h" #include "blackmisc/directoryutils.h" #include "blackmisc/fileutils.h" @@ -37,353 +38,12 @@ namespace BlackMisc { namespace FsCommon { - using FsRegistryPathPair = QList>; - const QStringList &CFsCommonUtil::getLogCategories() { static const QStringList cats({ CLogCategories::validation(), CLogCategories::driver() }); return cats; } - QString fsxDirFromRegistryImpl() - { - QString fsxPath; - const FsRegistryPathPair fsxRegistryPathPairs = - { - { QStringLiteral("HKEY_CURRENT_USER\\Software\\Microsoft\\Microsoft Games\\Flight Simulator\\10.0"), QStringLiteral("AppPath") }, - { QStringLiteral("HKEY_CURRENT_USER\\Software\\Microsoft\\Microsoft Games\\Flight Simulator - Steam Edition\\10.0"), QStringLiteral("AppPath") }, - { QStringLiteral("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Microsoft Games\\Flight Simulator\\10.0"), QStringLiteral("SetupPath") }, - { QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Microsoft Games\\Flight Simulator\\10.0"), QStringLiteral("SetupPath") } - }; - - for (const auto ®istryPair : fsxRegistryPathPairs) - { - const QSettings fsxRegistry(registryPair.first, QSettings::NativeFormat); - fsxPath = fsxRegistry.value(registryPair.second).toString().trimmed(); - - if (fsxPath.isEmpty()) { continue; } - fsxPath = CFileUtils::normalizeFilePathToQtStandard(fsxPath); - - // if path does NOT exists we continue to search, maybe another one does - const QDir dir(fsxPath); - if (dir.exists()) { break; } - fsxPath.clear(); - } - return CFileUtils::normalizeFilePathToQtStandard(fsxPath); - } - - const QString &CFsCommonUtil::fsxDirFromRegistry() - { - static const QString fsxPath(fsxDirFromRegistryImpl()); - return fsxPath; - } - - QString fsxDirImpl() - { - const QString dir(CFsCommonUtil::fsxDirFromRegistry()); - if (!dir.isEmpty()) { return dir; } - QStringList someDefaultDirs( - { - "C:/Program Files (x86)/Microsoft Games/Microsoft Flight Simulator X", - "C:/FSX" - }); - if (CBuildConfig::isLocalDeveloperDebugBuild()) - { - // developer directories - someDefaultDirs.push_back("P:/FSX (MSI)"); - } - return CFileUtils::findFirstExisting(someDefaultDirs); - } - - const QString &CFsCommonUtil::fsxDir() - { - static const QString dir(fsxDirImpl()); - return dir; - } - - QString fsxSimObjectsDirFromRegistryImpl() - { - const QString fsxPath = CFileUtils::normalizeFilePathToQtStandard(CFsCommonUtil::fsxDirFromRegistry()); - if (fsxPath.isEmpty()) { return {}; } - return CFsCommonUtil::fsxSimObjectsDirFromSimDir(fsxPath); - } - - const QString &CFsCommonUtil::fsxSimObjectsDirFromRegistry() - { - static const QString fsxPath(fsxSimObjectsDirFromRegistryImpl()); - return fsxPath; - } - - QString fsxSimObjectsDirImpl() - { - QString dir(CFsCommonUtil::fsxDir()); - if (dir.isEmpty()) { return {}; } - return CFsCommonUtil::fsxSimObjectsDirFromSimDir(dir); - } - - const QString &CFsCommonUtil::fsxSimObjectsDir() - { - static const QString dir(fsxSimObjectsDirImpl()); - return dir; - } - - QString CFsCommonUtil::fsxSimObjectsDirFromSimDir(const QString &simDir) - { - if (simDir.isEmpty()) { return {}; } - return CFileUtils::appendFilePaths(CFileUtils::normalizeFilePathToQtStandard(simDir), "SimObjects"); - } - - const QStringList &CFsCommonUtil::fsxSimObjectsExcludeDirectoryPatterns() - { - static const QStringList exclude - { - "SimObjects/Animals", - "SimObjects/Misc", - "SimObjects/GroundVehicles", - "SimObjects/Boats" - }; - return exclude; - } - - QString p3dDirFromRegistryImpl() - { - QString p3dPath; - FsRegistryPathPair p3dRegistryPathPairs = - { - // latest versions first - { QStringLiteral("HKEY_CURRENT_USER\\Software\\Lockheed Martin\\Prepar3d v6"), QStringLiteral("AppPath") }, - { QStringLiteral("HKEY_CURRENT_USER\\Software\\Lockheed Martin\\Prepar3d v5"), QStringLiteral("AppPath") }, - { QStringLiteral("HKEY_CURRENT_USER\\Software\\Lockheed Martin\\Prepar3d v4"), QStringLiteral("AppPath") }, - { QStringLiteral("HKEY_CURRENT_USER\\Software\\Lockheed Martin\\Prepar3d v3"), QStringLiteral("AppPath") }, - { QStringLiteral("HKEY_CURRENT_USER\\Software\\Lockheed Martin\\Prepar3d v2"), QStringLiteral("AppPath") }, - { QStringLiteral("HKEY_CURRENT_USER\\Software\\LockheedMartin\\Prepar3d"), QStringLiteral("AppPath") } - }; - for (const auto ®istryPair : p3dRegistryPathPairs) - { - const QSettings p3dRegistry(registryPair.first, QSettings::NativeFormat); - p3dPath = p3dRegistry.value(registryPair.second).toString().trimmed(); - - if (p3dPath.isEmpty()) { continue; } - p3dPath = CFileUtils::normalizeFilePathToQtStandard(p3dPath); - - // if path does NOT exists we continue to search, maybe another one does - const QDir dir(p3dPath); - if (dir.exists()) { break; } - p3dPath.clear(); - } - return p3dPath; - } - - const QString &CFsCommonUtil::p3dDirFromRegistry() - { - static const QString p3dPath = CFileUtils::normalizeFilePathToQtStandard(p3dDirFromRegistryImpl()); - return p3dPath; - } - - QString p3dDirImpl() - { - QString dir(CFsCommonUtil::p3dDirFromRegistry()); - if (!dir.isEmpty()) { return dir; } - const QStringList someDefaultDirs( - { - "C:/Program Files (x86)/Lockheed Martin/Prepar3D v4", - "C:/Program Files (x86)/Lockheed Martin/Prepar3D v3", - "C:/Program Files (x86)/Lockheed Martin/Prepar3D v2", - "C:/Program Files (x86)/Lockheed Martin/Prepar3D" - }); - return CFileUtils::findFirstExisting(someDefaultDirs); - } - - const QString &CFsCommonUtil::p3dDir() - { - static const QString dir(p3dDirImpl()); - return dir; - } - - QString p3dSimObjectsDirFromRegistryImpl() - { - const QString p3dPath = CFsCommonUtil::p3dDirFromRegistry(); - if (p3dPath.isEmpty()) { return {}; } - return CFsCommonUtil::fsxSimObjectsDirFromSimDir(p3dPath); - } - - const QString &CFsCommonUtil::p3dSimObjectsDirFromRegistry() - { - static const QString p3dPath(p3dSimObjectsDirFromRegistryImpl()); - return p3dPath; - } - - QString p3dSimObjectsDirImpl() - { - QString dir(CFsCommonUtil::p3dDir()); - if (dir.isEmpty()) { return {}; } - return CFsCommonUtil::p3dSimObjectsDirFromSimDir(dir); - } - - const QString &CFsCommonUtil::p3dSimObjectsDir() - { - static const QString dir(p3dSimObjectsDirImpl()); - return dir; - } - - QStringList CFsCommonUtil::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir) - { - // finding the user settings only works on P3D machine - QStringList allPaths = CFsCommonUtil::allFsxSimObjectPaths().values(); - const QString sod = CFileUtils::normalizeFilePathToQtStandard(simObjectsDir.isEmpty() ? CFsCommonUtil::fsxSimObjectsDir() : simObjectsDir); - if (!sod.isEmpty() && !allPaths.contains(sod, Qt::CaseInsensitive)) - { - // case insensitive is important here - allPaths.push_front(sod); - } - - allPaths.removeAll({}); // remove all empty - allPaths.removeDuplicates(); - allPaths.sort(Qt::CaseInsensitive); - return allPaths; - } - - QStringList CFsCommonUtil::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir, const QString &versionHint) - { - // finding the user settings only works on P3D machine - QStringList allPaths = CFsCommonUtil::allP3dAddOnXmlSimObjectPaths(versionHint).values(); - const QString sod = CFileUtils::normalizeFilePathToQtStandard(simObjectsDir.isEmpty() ? CFsCommonUtil::p3dSimObjectsDir() : simObjectsDir); - if (!sod.isEmpty() && !allPaths.contains(sod, Qt::CaseInsensitive)) - { - // case insensitive is important here - allPaths.push_front(sod); - } - - allPaths.removeAll({}); // remove all empty - allPaths.removeDuplicates(); - allPaths.sort(Qt::CaseInsensitive); - return allPaths; - } - - QString CFsCommonUtil::guessP3DVersion(const QString &candidate) - { - if (candidate.isEmpty()) { return "v5"; } - if (candidate.contains("v5", Qt::CaseInsensitive)) { return QStringLiteral("v5"); } - if (candidate.contains("v4", Qt::CaseInsensitive)) { return QStringLiteral("v4"); } - - if (candidate.contains("5", Qt::CaseInsensitive)) { return QStringLiteral("v5"); } - if (candidate.contains("4", Qt::CaseInsensitive)) { return QStringLiteral("v4"); } - - return "v5"; // that is the future (in 2020) - } - - QString CFsCommonUtil::p3dSimObjectsDirFromSimDir(const QString &simDir) - { - if (simDir.isEmpty()) { return {}; } - return CFileUtils::normalizeFilePathToQtStandard(CFileUtils::appendFilePaths(simDir, "SimObjects")); - } - - const QStringList &CFsCommonUtil::p3dSimObjectsExcludeDirectoryPatterns() - { - static const QStringList exclude - { - // FSX - "SimObjects/Animals", - "SimObjects/Misc", - "SimObjects/GroundVehicles", - "SimObjects/Boats", - - // P3D new - "SimObjects/Avatars", - "SimObjects/Countermeasures", - "SimObjects/Submersible", - "SimObjects/Weapons", - }; - return exclude; - } - - QString fs9DirFromRegistryImpl() - { - QString fs9Path; - FsRegistryPathPair fs9RegistryPathPairs = - { - { QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\DirectPlay\\Applications\\Microsoft Flight Simulator 2004"), QStringLiteral("AppPath") }, - { QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\DirectPlay\\Applications\\Microsoft Flight Simulator 2004"), QStringLiteral("AppPath") } - }; - - for (const auto ®istryPair : fs9RegistryPathPairs) - { - QSettings fs9Registry(registryPair.first, QSettings::NativeFormat); - fs9Path = fs9Registry.value(registryPair.second).toString().trimmed(); - - if (fs9Path.isEmpty()) { continue; } - fs9Path = CFileUtils::normalizeFilePathToQtStandard(fs9Path); - - // if path does NOT exists we continue to search, maybe another one does - const QDir dir(fs9Path); - if (dir.exists()) { break; } - fs9Path.clear(); - } - return fs9Path; - } - - const QString &CFsCommonUtil::fs9DirFromRegistry() - { - static const QString fs9Path(fs9DirFromRegistryImpl()); - return fs9Path; - } - - QString fs9DirImpl() - { - QString dir(CFsCommonUtil::fs9DirFromRegistry()); - if (!dir.isEmpty()) { return dir; } - const QStringList someDefaultDirs( - { - "C:/Flight Simulator 9", - "C:/FS9" - }); - return CFileUtils::findFirstExisting(someDefaultDirs); - } - - const QString &CFsCommonUtil::fs9Dir() - { - static const QString v(fs9DirImpl()); - return v; - } - - QString fs9AircraftDirFromRegistryImpl() - { - QString fs9Path = CFsCommonUtil::fs9DirFromRegistry(); - if (fs9Path.isEmpty()) { return {}; } - return CFsCommonUtil::fs9AircraftDirFromSimDir(fs9Path); - } - - const QString &CFsCommonUtil::fs9AircraftDirFromRegistry() - { - static const QString dir(fs9AircraftDirFromRegistryImpl()); - return dir; - } - - QString fs9AircraftDirImpl() - { - const QString dir(CFsCommonUtil::fs9Dir()); - if (dir.isEmpty()) { return {}; } - return CFsCommonUtil::fs9AircraftDirFromSimDir(dir); - } - - const QString &CFsCommonUtil::fs9AircraftDir() - { - static const QString dir(fs9AircraftDirImpl()); - return dir; - } - - QString CFsCommonUtil::fs9AircraftDirFromSimDir(const QString &simDir) - { - if (simDir.isEmpty()) { return {}; } - return CFileUtils::appendFilePaths(simDir, "Aircraft"); - } - - const QStringList &CFsCommonUtil::fs9AircraftObjectsExcludeDirectoryPatterns() - { - static const QStringList exclude; - return exclude; - } - bool CFsCommonUtil::adjustFileDirectory(CAircraftModel &model, const QString &simObjectsDirectory) { if (model.hasExistingCorrespondingFile()) { return true; } @@ -453,208 +113,6 @@ namespace BlackMisc return copied; } - QSet CFsCommonUtil::findP3dAddOnConfigFiles(const QString &versionHint) - { - static const QString cfgFile("add-ons.cfg"); - return CFsCommonUtil::findP3dConfigFiles(cfgFile, versionHint); - } - - QSet CFsCommonUtil::findP3dSimObjectsConfigFiles(const QString &versionHint) - { - static const QString cfgFile("simobjects.cfg"); - return CFsCommonUtil::findP3dConfigFiles(cfgFile, versionHint); - } - - QSet CFsCommonUtil::findP3dConfigFiles(const QString &configFile, const QString &versionHint) - { - // locations will be swift paths, I will go one level up and then search for Lockheed Martin - const QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); - QSet files; - for (const QString &path : locations) - { - const QString pathUp = CFileUtils::appendFilePaths(CFileUtils::pathUp(path), "Lockheed Martin"); - const QDir d(pathUp); - if (!d.exists()) { continue; } - if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"P3D config dir: '%1'") << d.absolutePath(); } - - // all versions sub directories - // looking for "add-ons.cfg" or simobjects.cfg - const QStringList entries = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - for (const QString &entry : entries) - { - // right version or just one file - if (entry.contains(versionHint, Qt::CaseInsensitive)) - { - const QString f = CFileUtils::appendFilePaths(d.absolutePath(), entry, configFile); - const QFileInfo fi(f); - if (fi.exists()) - { - files.insert(f); - if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"P3D config file: '%1'") << f; } - } - } // contains - } // entries - } - return files; - } - - QSet CFsCommonUtil::allConfigFilesPathValues(const QStringList &configFiles, bool checked, const QString &pathPrefix) - { - if (configFiles.isEmpty()) { return QSet(); } - QSet paths; - for (const QString &configFile : configFiles) - { - // manually parsing because QSettings did not work properly - const QString fileContent = CFileUtils::readFileToString(configFile); - if (fileContent.isEmpty()) { continue; } - const QList lines = splitLinesRefs(fileContent); - static const QString p("Path="); - for (const QStringRef &line : lines) - { - const int i = line.lastIndexOf(p, -1, Qt::CaseInsensitive); - if (i < 0 || line.endsWith('=')) { continue; } - const QStringRef path = line.mid(i + p.length()); - const QDir dir(QDir::fromNativeSeparators(pathPrefix.isEmpty() ? path.toString() : CFileUtils::appendFilePathsAndFixUnc(pathPrefix, path.toString()))); - if (!checked || dir.exists()) { paths.insert(dir.absolutePath()); } - } - } - return paths; - } - - QSet CFsCommonUtil::allP3dAddOnXmlSimObjectPaths(const QStringList &addOnPaths, bool checked) - { - if (addOnPaths.isEmpty()) { return QSet(); } - QSet simObjectPaths; - for (const QString &addOnPath : addOnPaths) - { - const QString filename = CFileUtils::appendFilePaths(addOnPath, "add-on.xml"); - QDomDocument doc; - QFile file(filename); - if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file)) { continue; } - if (CFsCommonUtil::logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"Reading '%1' from addon path: '%2'") << file.fileName() << addOnPath; } - - const QDomNodeList components = doc.elementsByTagName("AddOn.Component"); - for (int i = 0; i < components.size(); i++) - { - const QDomNode component = components.item(i); - const QDomElement category = component.firstChildElement("Category"); - const QString categoryValue = category.text(); - if (!caseInsensitiveStringCompare(categoryValue, QStringLiteral("SimObjects"))) { continue; } - const QDomElement path = component.firstChildElement("Path"); - const QString pathValue = CFileUtils::normalizeFilePathToQtStandard(path.text()); - const bool correctPath = pathValue.contains("Airplanes", Qt::CaseInsensitive) || - pathValue.contains("Rotorcraft", Qt::CaseInsensitive); - if (!correctPath) { continue; } - - // absolute or relative path - const QString fp = pathValue.left(3).contains(':') ? - pathValue : - CFileUtils::appendFilePaths(addOnPath, pathValue); - if (CFsCommonUtil::logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"Testing '%1' as addon path: '%2'") << fp << addOnPath; } - if (!checked || QDir(fp).exists()) - { - simObjectPaths.insert(CFileUtils::normalizeFilePathToQtStandard(fp)); - if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"P3D SimObjects path: '%1'") << fp; } - } - } // components - } // paths - - return simObjectPaths; - } - - QSet CFsCommonUtil::allP3dAddOnXmlSimObjectPaths(const QString &versionHint) - { - // all add-ons.cfg files - const QStringList addOnConfigFiles = CFsCommonUtil::findP3dAddOnConfigFiles(versionHint).values(); - - // all PATH values in those files - const QStringList addOnPaths = CFsCommonUtil::allConfigFilesPathValues(addOnConfigFiles, true, {}).values(); - - // based on all paths of all config files search the XML files - const QSet all = CFsCommonUtil::allP3dAddOnXmlSimObjectPaths(addOnPaths, true); - return all; - } - - QSet CFsCommonUtil::allFsxSimObjectPaths() - { - return CFsCommonUtil::fsxSimObjectsPaths(CFsCommonUtil::findFsxConfigFiles(), true); - } - - QStringList CFsCommonUtil::findFsxConfigFiles() - { - const QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); - QStringList files; - for (const QString &path : locations) - { - const QString file = CFileUtils::appendFilePaths(CFileUtils::pathUp(path), "Microsoft/FSX/fsx.cfg"); - const QFileInfo fi(file); - if (fi.exists()) - { - files.push_back(fi.absoluteFilePath()); - if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX config file: '%1'") << fi.absoluteFilePath(); } - } - } - return files; - } - - QSet CFsCommonUtil::fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked) - { - QSet paths; - for (const QString &fsxFile : fsxFiles) - { - paths.unite(CFsCommonUtil::fsxSimObjectsPaths(fsxFile, checked)); - } - return paths; - } - - QSet CFsCommonUtil::fsxSimObjectsPaths(const QString &fsxFile, bool checked) - { - const QString fileContent = CFileUtils::readFileToString(fsxFile); - if (fileContent.isEmpty()) { return QSet(); } - const QList lines = splitLinesRefs(fileContent); - static const QString p("SimObjectPaths."); - - const QFileInfo fsxFileInfo(fsxFile); - const QString relPath = fsxFileInfo.absolutePath(); - - QSet paths; - for (const QStringRef &line : lines) - { - const int i1 = line.lastIndexOf(p, -1, Qt::CaseInsensitive); - if (i1 < 0) { continue; } - const int i2 = line.lastIndexOf('='); - if (i2 < 0 || i1 >= i2 || line.endsWith('=')) { continue; } - const QStringRef path = line.mid(i2 + 1); - QString soPath = QDir::fromNativeSeparators(path.toString()); - if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path checked: '%1' in '%2'") << line << fsxFile; } - - // ignore exclude patterns - if (containsAny(soPath, CFsCommonUtil::fsxSimObjectsExcludeDirectoryPatterns(), Qt::CaseInsensitive)) { continue; } - - // make absolute - if (!soPath.left(3).contains(':')) { soPath = CFileUtils::appendFilePaths(relPath, soPath); } - - const QDir dir(soPath); // always absolute path now - if (checked && !dir.exists()) - { - // skip, not existing - if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path skipped, not existing: '%1' in '%2'") << dir.absolutePath() << fsxFile; } - continue; - } - - const QString afp = dir.absolutePath().toLower(); - if (!CDirectoryUtils::containsFileInDir(afp, airFileFilter(), true)) - { - if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path: Skipping '%1' from '%2', no '%3' file") << afp << fsxFile << airFileFilter(); } - continue; - } - - paths.insert(afp); - if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path: '%1' from '%2'") << afp << fsxFile; } - } - return paths; - } - CStatusMessageList CFsCommonUtil::validateAircraftConfigFiles(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &wasStopped) { CStatusMessage m; @@ -721,24 +179,18 @@ namespace BlackMisc CStatusMessageList CFsCommonUtil::validateP3DSimObjectsPath(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &wasStopped, const QString &simulatorDir) { - const QString simObjectsDir = simulatorDir.isEmpty() ? CFsCommonUtil::p3dSimObjectsDir() : CFsCommonUtil::p3dSimObjectsDirFromSimDir(simulatorDir); - const QStringList simObjectPaths = CFsCommonUtil::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(simObjectsDir, guessP3DVersion(simObjectsDir)); + const QString simObjectsDir = simulatorDir.isEmpty() ? CFsDirectories::p3dSimObjectsDir() : CFsDirectories::p3dSimObjectsDirFromSimDir(simulatorDir); + const QStringList simObjectPaths = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(simObjectsDir, CFsDirectories::guessP3DVersion(simObjectsDir)); return CFsCommonUtil::validateSimObjectsPath(QSet(simObjectPaths.begin(), simObjectPaths.end()), models, validModels, invalidModels, ignoreEmptyFileNames, stopAtFailedFiles, wasStopped); } CStatusMessageList CFsCommonUtil::validateFSXSimObjectsPath(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &stopped, const QString &simulatorDir) { Q_UNUSED(simulatorDir) - const QStringList simObjectPaths = CFsCommonUtil::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(); + const QStringList simObjectPaths = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(); return CFsCommonUtil::validateSimObjectsPath(QSet(simObjectPaths.begin(), simObjectPaths.end()), models, validModels, invalidModels, ignoreEmptyFileNames, stopAtFailedFiles, stopped); } - const QString CFsCommonUtil::airFileFilter() - { - static const QString a("*.air"); - return a; - } - CStatusMessageList CFsCommonUtil::validateSimObjectsPath( const QSet &simObjectDirs, const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, @@ -799,11 +251,6 @@ namespace BlackMisc return msgs; } - - bool CFsCommonUtil::logConfigPathReading() - { - return true; - } } // namespace } // namespace } // namespace diff --git a/src/blackmisc/simulation/fscommon/fscommonutil.h b/src/blackmisc/simulation/fscommon/fscommonutil.h index 2e2a05243..2e96cbec1 100644 --- a/src/blackmisc/simulation/fscommon/fscommonutil.h +++ b/src/blackmisc/simulation/fscommon/fscommonutil.h @@ -35,69 +35,6 @@ namespace BlackMisc //! Constructor CFsCommonUtil() = delete; - //! FSX directory obtained from registry - static const QString &fsxDirFromRegistry(); - - //! FSX directory from different sources - static const QString &fsxDir(); - - //! FSX's simObject directory from registry - static const QString &fsxSimObjectsDirFromRegistry(); - - //! FSX's simobject dir, resolved from multiple sources - static const QString &fsxSimObjectsDir(); - - //! FSX aircraft dir, relative to simulator directory - static QString fsxSimObjectsDirFromSimDir(const QString &simDir); - - //! Exclude directories for simObjects - static const QStringList &fsxSimObjectsExcludeDirectoryPatterns(); - - //! FSX's simObject dir and the add on dirs - static QStringList fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir = ""); - - //! P3D's simObject dir and the add on dirs - static QStringList p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir, const QString &versionHint); - - //! Guess the P3D version such as v4, v5 - static QString guessP3DVersion(const QString &candidate); - - //! P3D directory obtained from registry - static const QString &p3dDirFromRegistry(); - - //! P3D directory from different sources - static const QString &p3dDir(); - - //! P3D's simObject directory from registry - static const QString &p3dSimObjectsDirFromRegistry(); - - //! P3D's simObject dir, resolved from multiple sources - static const QString &p3dSimObjectsDir(); - - //! P3D aircraft dir, relative to simulator directory - static QString p3dSimObjectsDirFromSimDir(const QString &simDir); - - //! Exclude directories for simObjects - static const QStringList &p3dSimObjectsExcludeDirectoryPatterns(); - - //! FS9 directory obtained from registry - static const QString &fs9DirFromRegistry(); - - //! FS9 directory obtained from multiple sources - static const QString &fs9Dir(); - - //! FS9's aircraft directory from registry - static const QString &fs9AircraftDirFromRegistry(); - - //! FS9's aircraft directory - static const QString &fs9AircraftDir(); - - //! FS9 aircraft dir, relative to simulator directory - static QString fs9AircraftDirFromSimDir(const QString &simDir); - - //! Exclude directories for aircraft objects - static const QStringList &fs9AircraftObjectsExcludeDirectoryPatterns(); - //! Adjust file directory static bool adjustFileDirectory(CAircraftModel &model, const QString &simObjectsDirectory); @@ -107,40 +44,6 @@ namespace BlackMisc //! Copy the terrain probe static int copyFsxTerrainProbeFiles(const QString &simObjectDir, CStatusMessageList &messages); - //! Find the config files (add-ons.cfg) - //! \note "C:/Users/Joe Doe/AppData/Roaming/Lockheed Martin/Prepar3D v4" - //! \param versionHint like "v5" - static QSet findP3dAddOnConfigFiles(const QString &versionHint = "v5"); - - //! Find the config files (simobjects.cfg) - //! \note "C:/Users/Joe Doe/AppData/Roaming/Lockheed Martin/Prepar3D v4" - //! \param versionHint like "v5" - static QSet findP3dSimObjectsConfigFiles(const QString &versionHint = "v5"); - - //! All PATH values from the config files - static QSet allConfigFilesPathValues(const QStringList &configFiles, bool checked, const QString &pathPrefix); - - //! All add-on paths from the XML add-on files "add-on.xml" - static QSet allP3dAddOnXmlSimObjectPaths(const QStringList &addOnPaths, bool checked); - - //! All add-on paths from the XML add-on files "add-on.xml" files, use CFsCommonUtil::findP3dAddOnConfigFiles to find config files - static QSet allP3dAddOnXmlSimObjectPaths(const QString &versionHint = "v4"); - - //! Get all the SimObjects paths from all config files - static QSet allFsxSimObjectPaths(); - - //! Find the config files (fsx.cfg) - // C:/Users/Joe Doe/AppData/Roaming/Microsoft/FSX/fsx.cfg - static QStringList findFsxConfigFiles(); - - //! Get all the SimObjects paths from fsx.cfg - // SimObjectPaths.0=SimObjects\Airplanes - static QSet fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked); - - //! Get all the SimObjects files from fsx.cfg - // SimObjectPaths.0=SimObjects\Airplanes - static QSet fsxSimObjectsPaths(const QString &fsxFile, bool checked); - //! Validate aircraft.cfg entries (sometimes also sim.cfg) //! \remark only for FSX/P3D/FS9 models static CStatusMessageList validateAircraftConfigFiles(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &wasStopped); @@ -153,21 +56,10 @@ namespace BlackMisc //! \remark only for FSX static CStatusMessageList validateFSXSimObjectsPath(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &wasStopped, const QString &simulatorDir); - //! .air file filter - static const QString airFileFilter(); - private: - //! Utility functions - //! @{ - static QSet findP3dConfigFiles(const QString &configFile, const QString &versionHint = "v5"); - //! @} - //! Validate if known SimObjects path are used //! \remark only for P3D/FSX static CStatusMessageList validateSimObjectsPath(const QSet &simObjectDirs, const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &stopped); - - //! Log the reading of config files - static bool logConfigPathReading(); }; } // namespace } // namespace diff --git a/src/blackmisc/simulation/fscommon/fsdirectories.cpp b/src/blackmisc/simulation/fscommon/fsdirectories.cpp new file mode 100644 index 000000000..0bfcea306 --- /dev/null +++ b/src/blackmisc/simulation/fscommon/fsdirectories.cpp @@ -0,0 +1,600 @@ +/* Copyright (C) 2013 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +#include "blackmisc/simulation/fscommon/fsdirectories.h" +#include "blackmisc/swiftdirectories.h" +#include "blackmisc/directoryutils.h" +#include "blackmisc/fileutils.h" +#include "blackmisc/stringutils.h" +#include "blackmisc/logmessage.h" +#include "blackconfig/buildconfig.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace BlackConfig; + +namespace BlackMisc +{ + namespace Simulation + { + namespace FsCommon + { + using FsRegistryPathPair = QList>; + + const QStringList &CFsDirectories::getLogCategories() + { + static const QStringList cats({ CLogCategories::validation(), CLogCategories::driver() }); + return cats; + } + + QString fsxDirFromRegistryImpl() + { + QString fsxPath; + const FsRegistryPathPair fsxRegistryPathPairs = + { + { QStringLiteral("HKEY_CURRENT_USER\\Software\\Microsoft\\Microsoft Games\\Flight Simulator\\10.0"), QStringLiteral("AppPath") }, + { QStringLiteral("HKEY_CURRENT_USER\\Software\\Microsoft\\Microsoft Games\\Flight Simulator - Steam Edition\\10.0"), QStringLiteral("AppPath") }, + { QStringLiteral("HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Microsoft Games\\Flight Simulator\\10.0"), QStringLiteral("SetupPath") }, + { QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Microsoft Games\\Flight Simulator\\10.0"), QStringLiteral("SetupPath") } + }; + + for (const auto ®istryPair : fsxRegistryPathPairs) + { + const QSettings fsxRegistry(registryPair.first, QSettings::NativeFormat); + fsxPath = fsxRegistry.value(registryPair.second).toString().trimmed(); + + if (fsxPath.isEmpty()) { continue; } + fsxPath = CFileUtils::normalizeFilePathToQtStandard(fsxPath); + + // if path does NOT exists we continue to search, maybe another one does + const QDir dir(fsxPath); + if (dir.exists()) { break; } + fsxPath.clear(); + } + return CFileUtils::normalizeFilePathToQtStandard(fsxPath); + } + + const QString &CFsDirectories::fsxDirFromRegistry() + { + static const QString fsxPath(fsxDirFromRegistryImpl()); + return fsxPath; + } + + QString fsxDirImpl() + { + const QString dir(CFsDirectories::fsxDirFromRegistry()); + if (!dir.isEmpty()) { return dir; } + QStringList someDefaultDirs( + { + "C:/Program Files (x86)/Microsoft Games/Microsoft Flight Simulator X", + "C:/FSX" + }); + if (CBuildConfig::isLocalDeveloperDebugBuild()) + { + // developer directories + someDefaultDirs.push_back("P:/FSX (MSI)"); + } + return CFileUtils::findFirstExisting(someDefaultDirs); + } + + const QString &CFsDirectories::fsxDir() + { + static const QString dir(fsxDirImpl()); + return dir; + } + + QString fsxSimObjectsDirFromRegistryImpl() + { + const QString fsxPath = CFileUtils::normalizeFilePathToQtStandard(CFsDirectories::fsxDirFromRegistry()); + if (fsxPath.isEmpty()) { return {}; } + return CFsDirectories::fsxSimObjectsDirFromSimDir(fsxPath); + } + + const QString &CFsDirectories::fsxSimObjectsDirFromRegistry() + { + static const QString fsxPath(fsxSimObjectsDirFromRegistryImpl()); + return fsxPath; + } + + QString fsxSimObjectsDirImpl() + { + QString dir(CFsDirectories::fsxDir()); + if (dir.isEmpty()) { return {}; } + return CFsDirectories::fsxSimObjectsDirFromSimDir(dir); + } + + const QString &CFsDirectories::fsxSimObjectsDir() + { + static const QString dir(fsxSimObjectsDirImpl()); + return dir; + } + + QString CFsDirectories::fsxSimObjectsDirFromSimDir(const QString &simDir) + { + if (simDir.isEmpty()) { return {}; } + return CFileUtils::appendFilePaths(CFileUtils::normalizeFilePathToQtStandard(simDir), "SimObjects"); + } + + const QStringList &CFsDirectories::fsxSimObjectsExcludeDirectoryPatterns() + { + static const QStringList exclude + { + "SimObjects/Animals", + "SimObjects/Misc", + "SimObjects/GroundVehicles", + "SimObjects/Boats" + }; + return exclude; + } + + QString p3dDirFromRegistryImpl() + { + QString p3dPath; + FsRegistryPathPair p3dRegistryPathPairs = + { + // latest versions first + { QStringLiteral("HKEY_CURRENT_USER\\Software\\Lockheed Martin\\Prepar3d v6"), QStringLiteral("AppPath") }, + { QStringLiteral("HKEY_CURRENT_USER\\Software\\Lockheed Martin\\Prepar3d v5"), QStringLiteral("AppPath") }, + { QStringLiteral("HKEY_CURRENT_USER\\Software\\Lockheed Martin\\Prepar3d v4"), QStringLiteral("AppPath") }, + { QStringLiteral("HKEY_CURRENT_USER\\Software\\Lockheed Martin\\Prepar3d v3"), QStringLiteral("AppPath") }, + { QStringLiteral("HKEY_CURRENT_USER\\Software\\Lockheed Martin\\Prepar3d v2"), QStringLiteral("AppPath") }, + { QStringLiteral("HKEY_CURRENT_USER\\Software\\LockheedMartin\\Prepar3d"), QStringLiteral("AppPath") } + }; + for (const auto ®istryPair : p3dRegistryPathPairs) + { + const QSettings p3dRegistry(registryPair.first, QSettings::NativeFormat); + p3dPath = p3dRegistry.value(registryPair.second).toString().trimmed(); + + if (p3dPath.isEmpty()) { continue; } + p3dPath = CFileUtils::normalizeFilePathToQtStandard(p3dPath); + + // if path does NOT exists we continue to search, maybe another one does + const QDir dir(p3dPath); + if (dir.exists()) { break; } + p3dPath.clear(); + } + return p3dPath; + } + + const QString &CFsDirectories::p3dDirFromRegistry() + { + static const QString p3dPath = CFileUtils::normalizeFilePathToQtStandard(p3dDirFromRegistryImpl()); + return p3dPath; + } + + QString p3dDirImpl() + { + QString dir(CFsDirectories::p3dDirFromRegistry()); + if (!dir.isEmpty()) { return dir; } + const QStringList someDefaultDirs( + { + "C:/Program Files (x86)/Lockheed Martin/Prepar3D v4", + "C:/Program Files (x86)/Lockheed Martin/Prepar3D v3", + "C:/Program Files (x86)/Lockheed Martin/Prepar3D v2", + "C:/Program Files (x86)/Lockheed Martin/Prepar3D" + }); + return CFileUtils::findFirstExisting(someDefaultDirs); + } + + const QString &CFsDirectories::p3dDir() + { + static const QString dir(p3dDirImpl()); + return dir; + } + + QString p3dSimObjectsDirFromRegistryImpl() + { + const QString p3dPath = CFsDirectories::p3dDirFromRegistry(); + if (p3dPath.isEmpty()) { return {}; } + return CFsDirectories::fsxSimObjectsDirFromSimDir(p3dPath); + } + + const QString &CFsDirectories::p3dSimObjectsDirFromRegistry() + { + static const QString p3dPath(p3dSimObjectsDirFromRegistryImpl()); + return p3dPath; + } + + QString p3dSimObjectsDirImpl() + { + QString dir(CFsDirectories::p3dDir()); + if (dir.isEmpty()) { return {}; } + return CFsDirectories::p3dSimObjectsDirFromSimDir(dir); + } + + const QString &CFsDirectories::p3dSimObjectsDir() + { + static const QString dir(p3dSimObjectsDirImpl()); + return dir; + } + + QStringList CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir) + { + // finding the user settings only works on P3D machine + QStringList allPaths = CFsDirectories::allFsxSimObjectPaths().values(); + const QString sod = CFileUtils::normalizeFilePathToQtStandard(simObjectsDir.isEmpty() ? CFsDirectories::fsxSimObjectsDir() : simObjectsDir); + if (!sod.isEmpty() && !allPaths.contains(sod, Qt::CaseInsensitive)) + { + // case insensitive is important here + allPaths.push_front(sod); + } + + allPaths.removeAll({}); // remove all empty + allPaths.removeDuplicates(); + allPaths.sort(Qt::CaseInsensitive); + return allPaths; + } + + QStringList CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir, const QString &versionHint) + { + // finding the user settings only works on P3D machine + QStringList allPaths = CFsDirectories::allP3dAddOnXmlSimObjectPaths(versionHint).values(); + const QString sod = CFileUtils::normalizeFilePathToQtStandard(simObjectsDir.isEmpty() ? CFsDirectories::p3dSimObjectsDir() : simObjectsDir); + if (!sod.isEmpty() && !allPaths.contains(sod, Qt::CaseInsensitive)) + { + // case insensitive is important here + allPaths.push_front(sod); + } + + allPaths.removeAll({}); // remove all empty + allPaths.removeDuplicates(); + allPaths.sort(Qt::CaseInsensitive); + return allPaths; + } + + QString CFsDirectories::guessP3DVersion(const QString &candidate) + { + if (candidate.isEmpty()) { return "v5"; } + if (candidate.contains("v5", Qt::CaseInsensitive)) { return QStringLiteral("v5"); } + if (candidate.contains("v4", Qt::CaseInsensitive)) { return QStringLiteral("v4"); } + + if (candidate.contains("5", Qt::CaseInsensitive)) { return QStringLiteral("v5"); } + if (candidate.contains("4", Qt::CaseInsensitive)) { return QStringLiteral("v4"); } + + return "v5"; // that is the future (in 2020) + } + + QString CFsDirectories::p3dSimObjectsDirFromSimDir(const QString &simDir) + { + if (simDir.isEmpty()) { return {}; } + return CFileUtils::normalizeFilePathToQtStandard(CFileUtils::appendFilePaths(simDir, "SimObjects")); + } + + const QStringList &CFsDirectories::p3dSimObjectsExcludeDirectoryPatterns() + { + static const QStringList exclude + { + // FSX + "SimObjects/Animals", + "SimObjects/Misc", + "SimObjects/GroundVehicles", + "SimObjects/Boats", + + // P3D new + "SimObjects/Avatars", + "SimObjects/Countermeasures", + "SimObjects/Submersible", + "SimObjects/Weapons", + }; + return exclude; + } + + QString fs9DirFromRegistryImpl() + { + QString fs9Path; + FsRegistryPathPair fs9RegistryPathPairs = + { + { QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\DirectPlay\\Applications\\Microsoft Flight Simulator 2004"), QStringLiteral("AppPath") }, + { QStringLiteral("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\DirectPlay\\Applications\\Microsoft Flight Simulator 2004"), QStringLiteral("AppPath") } + }; + + for (const auto ®istryPair : fs9RegistryPathPairs) + { + QSettings fs9Registry(registryPair.first, QSettings::NativeFormat); + fs9Path = fs9Registry.value(registryPair.second).toString().trimmed(); + + if (fs9Path.isEmpty()) { continue; } + fs9Path = CFileUtils::normalizeFilePathToQtStandard(fs9Path); + + // if path does NOT exists we continue to search, maybe another one does + const QDir dir(fs9Path); + if (dir.exists()) { break; } + fs9Path.clear(); + } + return fs9Path; + } + + const QString &CFsDirectories::fs9DirFromRegistry() + { + static const QString fs9Path(fs9DirFromRegistryImpl()); + return fs9Path; + } + + QString fs9DirImpl() + { + QString dir(CFsDirectories::fs9DirFromRegistry()); + if (!dir.isEmpty()) { return dir; } + const QStringList someDefaultDirs( + { + "C:/Flight Simulator 9", + "C:/FS9" + }); + return CFileUtils::findFirstExisting(someDefaultDirs); + } + + const QString &CFsDirectories::fs9Dir() + { + static const QString v(fs9DirImpl()); + return v; + } + + QString fs9AircraftDirFromRegistryImpl() + { + QString fs9Path = CFsDirectories::fs9DirFromRegistry(); + if (fs9Path.isEmpty()) { return {}; } + return CFsDirectories::fs9AircraftDirFromSimDir(fs9Path); + } + + const QString &CFsDirectories::fs9AircraftDirFromRegistry() + { + static const QString dir(fs9AircraftDirFromRegistryImpl()); + return dir; + } + + QString fs9AircraftDirImpl() + { + const QString dir(CFsDirectories::fs9Dir()); + if (dir.isEmpty()) { return {}; } + return CFsDirectories::fs9AircraftDirFromSimDir(dir); + } + + const QString &CFsDirectories::fs9AircraftDir() + { + static const QString dir(fs9AircraftDirImpl()); + return dir; + } + + QString CFsDirectories::fs9AircraftDirFromSimDir(const QString &simDir) + { + if (simDir.isEmpty()) { return {}; } + return CFileUtils::appendFilePaths(simDir, "Aircraft"); + } + + const QStringList &CFsDirectories::fs9AircraftObjectsExcludeDirectoryPatterns() + { + static const QStringList exclude; + return exclude; + } + + QSet CFsDirectories::findP3dAddOnConfigFiles(const QString &versionHint) + { + static const QString cfgFile("add-ons.cfg"); + return CFsDirectories::findP3dConfigFiles(cfgFile, versionHint); + } + + QSet CFsDirectories::findP3dSimObjectsConfigFiles(const QString &versionHint) + { + static const QString cfgFile("simobjects.cfg"); + return CFsDirectories::findP3dConfigFiles(cfgFile, versionHint); + } + + QSet CFsDirectories::findP3dConfigFiles(const QString &configFile, const QString &versionHint) + { + // locations will be swift paths, I will go one level up and then search for Lockheed Martin + const QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); + QSet files; + for (const QString &path : locations) + { + const QString pathUp = CFileUtils::appendFilePaths(CFileUtils::pathUp(path), "Lockheed Martin"); + const QDir d(pathUp); + if (!d.exists()) { continue; } + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"P3D config dir: '%1'") << d.absolutePath(); } + + // all versions sub directories + // looking for "add-ons.cfg" or simobjects.cfg + const QStringList entries = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + for (const QString &entry : entries) + { + // right version or just one file + if (entry.contains(versionHint, Qt::CaseInsensitive)) + { + const QString f = CFileUtils::appendFilePaths(d.absolutePath(), entry, configFile); + const QFileInfo fi(f); + if (fi.exists()) + { + files.insert(f); + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"P3D config file: '%1'") << f; } + } + } // contains + } // entries + } + return files; + } + + QSet CFsDirectories::allConfigFilesPathValues(const QStringList &configFiles, bool checked, const QString &pathPrefix) + { + if (configFiles.isEmpty()) { return QSet(); } + QSet paths; + for (const QString &configFile : configFiles) + { + // manually parsing because QSettings did not work properly + const QString fileContent = CFileUtils::readFileToString(configFile); + if (fileContent.isEmpty()) { continue; } + const QList lines = splitLinesRefs(fileContent); + static const QString p("Path="); + for (const QStringRef &line : lines) + { + const int i = line.lastIndexOf(p, -1, Qt::CaseInsensitive); + if (i < 0 || line.endsWith('=')) { continue; } + const QStringRef path = line.mid(i + p.length()); + const QDir dir(QDir::fromNativeSeparators(pathPrefix.isEmpty() ? path.toString() : CFileUtils::appendFilePathsAndFixUnc(pathPrefix, path.toString()))); + if (!checked || dir.exists()) { paths.insert(dir.absolutePath()); } + } + } + return paths; + } + + QSet CFsDirectories::allP3dAddOnXmlSimObjectPaths(const QStringList &addOnPaths, bool checked) + { + if (addOnPaths.isEmpty()) { return QSet(); } + QSet simObjectPaths; + for (const QString &addOnPath : addOnPaths) + { + const QString filename = CFileUtils::appendFilePaths(addOnPath, "add-on.xml"); + QDomDocument doc; + QFile file(filename); + if (!file.open(QIODevice::ReadOnly) || !doc.setContent(&file)) { continue; } + if (CFsDirectories::logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"Reading '%1' from addon path: '%2'") << file.fileName() << addOnPath; } + + const QDomNodeList components = doc.elementsByTagName("AddOn.Component"); + for (int i = 0; i < components.size(); i++) + { + const QDomNode component = components.item(i); + const QDomElement category = component.firstChildElement("Category"); + const QString categoryValue = category.text(); + if (!caseInsensitiveStringCompare(categoryValue, QStringLiteral("SimObjects"))) { continue; } + const QDomElement path = component.firstChildElement("Path"); + const QString pathValue = CFileUtils::normalizeFilePathToQtStandard(path.text()); + const bool correctPath = pathValue.contains("Airplanes", Qt::CaseInsensitive) || + pathValue.contains("Rotorcraft", Qt::CaseInsensitive); + if (!correctPath) { continue; } + + // absolute or relative path + const QString fp = pathValue.left(3).contains(':') ? + pathValue : + CFileUtils::appendFilePaths(addOnPath, pathValue); + if (CFsDirectories::logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"Testing '%1' as addon path: '%2'") << fp << addOnPath; } + if (!checked || QDir(fp).exists()) + { + simObjectPaths.insert(CFileUtils::normalizeFilePathToQtStandard(fp)); + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"P3D SimObjects path: '%1'") << fp; } + } + } // components + } // paths + + return simObjectPaths; + } + + QSet CFsDirectories::allP3dAddOnXmlSimObjectPaths(const QString &versionHint) + { + // all add-ons.cfg files + const QStringList addOnConfigFiles = CFsDirectories::findP3dAddOnConfigFiles(versionHint).values(); + + // all PATH values in those files + const QStringList addOnPaths = CFsDirectories::allConfigFilesPathValues(addOnConfigFiles, true, {}).values(); + + // based on all paths of all config files search the XML files + const QSet all = CFsDirectories::allP3dAddOnXmlSimObjectPaths(addOnPaths, true); + return all; + } + + QSet CFsDirectories::allFsxSimObjectPaths() + { + return CFsDirectories::fsxSimObjectsPaths(CFsDirectories::findFsxConfigFiles(), true); + } + + QStringList CFsDirectories::findFsxConfigFiles() + { + const QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation); + QStringList files; + for (const QString &path : locations) + { + const QString file = CFileUtils::appendFilePaths(CFileUtils::pathUp(path), "Microsoft/FSX/fsx.cfg"); + const QFileInfo fi(file); + if (fi.exists()) + { + files.push_back(fi.absoluteFilePath()); + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX config file: '%1'") << fi.absoluteFilePath(); } + } + } + return files; + } + + QSet CFsDirectories::fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked) + { + QSet paths; + for (const QString &fsxFile : fsxFiles) + { + paths.unite(CFsDirectories::fsxSimObjectsPaths(fsxFile, checked)); + } + return paths; + } + + QSet CFsDirectories::fsxSimObjectsPaths(const QString &fsxFile, bool checked) + { + const QString fileContent = CFileUtils::readFileToString(fsxFile); + if (fileContent.isEmpty()) { return QSet(); } + const QList lines = splitLinesRefs(fileContent); + static const QString p("SimObjectPaths."); + + const QFileInfo fsxFileInfo(fsxFile); + const QString relPath = fsxFileInfo.absolutePath(); + + QSet paths; + for (const QStringRef &line : lines) + { + const int i1 = line.lastIndexOf(p, -1, Qt::CaseInsensitive); + if (i1 < 0) { continue; } + const int i2 = line.lastIndexOf('='); + if (i2 < 0 || i1 >= i2 || line.endsWith('=')) { continue; } + const QStringRef path = line.mid(i2 + 1); + QString soPath = QDir::fromNativeSeparators(path.toString()); + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path checked: '%1' in '%2'") << line << fsxFile; } + + // ignore exclude patterns + if (containsAny(soPath, CFsDirectories::fsxSimObjectsExcludeDirectoryPatterns(), Qt::CaseInsensitive)) { continue; } + + // make absolute + if (!soPath.left(3).contains(':')) { soPath = CFileUtils::appendFilePaths(relPath, soPath); } + + const QDir dir(soPath); // always absolute path now + if (checked && !dir.exists()) + { + // skip, not existing + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path skipped, not existing: '%1' in '%2'") << dir.absolutePath() << fsxFile; } + continue; + } + + const QString afp = dir.absolutePath().toLower(); + if (!CDirectoryUtils::containsFileInDir(afp, airFileFilter(), true)) + { + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path: Skipping '%1' from '%2', no '%3' file") << afp << fsxFile << airFileFilter(); } + continue; + } + + paths.insert(afp); + if (logConfigPathReading()) { CLogMessage(static_cast(nullptr)).info(u"FSX SimObjects path: '%1' from '%2'") << afp << fsxFile; } + } + return paths; + } + + const QString CFsDirectories::airFileFilter() + { + static const QString a("*.air"); + return a; + } + + bool CFsDirectories::logConfigPathReading() + { + return true; + } + } // namespace + } // namespace +} // namespace diff --git a/src/blackmisc/simulation/fscommon/fsdirectories.h b/src/blackmisc/simulation/fscommon/fsdirectories.h new file mode 100644 index 000000000..9776c245c --- /dev/null +++ b/src/blackmisc/simulation/fscommon/fsdirectories.h @@ -0,0 +1,150 @@ +/* Copyright (C) 2013 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISC_SIMULATION_FSDIRECTORIES_H +#define BLACKMISC_SIMULATION_FSDIRECTORIES_H + +#include "blackmisc/logcategories.h" +#include "blackmisc/blackmiscexport.h" + +#include +#include +#include + +namespace BlackMisc +{ + namespace Simulation + { + namespace FsCommon + { + //! FS9/FSX/P3D directories + class BLACKMISC_EXPORT CFsDirectories + { + public: + //! Log categories + static const QStringList &getLogCategories(); + + //! Constructor + CFsDirectories() = delete; + + //! FSX directory obtained from registry + static const QString &fsxDirFromRegistry(); + + //! FSX directory from different sources + static const QString &fsxDir(); + + //! FSX's simObject directory from registry + static const QString &fsxSimObjectsDirFromRegistry(); + + //! FSX's simobject dir, resolved from multiple sources + static const QString &fsxSimObjectsDir(); + + //! FSX aircraft dir, relative to simulator directory + static QString fsxSimObjectsDirFromSimDir(const QString &simDir); + + //! Exclude directories for simObjects + static const QStringList &fsxSimObjectsExcludeDirectoryPatterns(); + + //! FSX's simObject dir and the add on dirs + static QStringList fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir = ""); + + //! P3D's simObject dir and the add on dirs + static QStringList p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(const QString &simObjectsDir, const QString &versionHint); + + //! Guess the P3D version such as v4, v5 + static QString guessP3DVersion(const QString &candidate); + + //! P3D directory obtained from registry + static const QString &p3dDirFromRegistry(); + + //! P3D directory from different sources + static const QString &p3dDir(); + + //! P3D's simObject directory from registry + static const QString &p3dSimObjectsDirFromRegistry(); + + //! P3D's simObject dir, resolved from multiple sources + static const QString &p3dSimObjectsDir(); + + //! P3D aircraft dir, relative to simulator directory + static QString p3dSimObjectsDirFromSimDir(const QString &simDir); + + //! Exclude directories for simObjects + static const QStringList &p3dSimObjectsExcludeDirectoryPatterns(); + + //! FS9 directory obtained from registry + static const QString &fs9DirFromRegistry(); + + //! FS9 directory obtained from multiple sources + static const QString &fs9Dir(); + + //! FS9's aircraft directory from registry + static const QString &fs9AircraftDirFromRegistry(); + + //! FS9's aircraft directory + static const QString &fs9AircraftDir(); + + //! FS9 aircraft dir, relative to simulator directory + static QString fs9AircraftDirFromSimDir(const QString &simDir); + + //! Exclude directories for aircraft objects + static const QStringList &fs9AircraftObjectsExcludeDirectoryPatterns(); + + //! Find the config files (add-ons.cfg) + //! \note "C:/Users/Joe Doe/AppData/Roaming/Lockheed Martin/Prepar3D v4" + //! \param versionHint like "v5" + static QSet findP3dAddOnConfigFiles(const QString &versionHint = "v5"); + + //! Find the config files (simobjects.cfg) + //! \note "C:/Users/Joe Doe/AppData/Roaming/Lockheed Martin/Prepar3D v4" + //! \param versionHint like "v5" + static QSet findP3dSimObjectsConfigFiles(const QString &versionHint = "v5"); + + //! All PATH values from the config files + static QSet allConfigFilesPathValues(const QStringList &configFiles, bool checked, const QString &pathPrefix); + + //! All add-on paths from the XML add-on files "add-on.xml" + static QSet allP3dAddOnXmlSimObjectPaths(const QStringList &addOnPaths, bool checked); + + //! All add-on paths from the XML add-on files "add-on.xml" files, use CFsCommonUtil::findP3dAddOnConfigFiles to find config files + static QSet allP3dAddOnXmlSimObjectPaths(const QString &versionHint = "v4"); + + //! Get all the SimObjects paths from all config files + static QSet allFsxSimObjectPaths(); + + //! Find the config files (fsx.cfg) + // C:/Users/Joe Doe/AppData/Roaming/Microsoft/FSX/fsx.cfg + static QStringList findFsxConfigFiles(); + + //! Get all the SimObjects paths from fsx.cfg + // SimObjectPaths.0=SimObjects\Airplanes + static QSet fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked); + + //! Get all the SimObjects files from fsx.cfg + // SimObjectPaths.0=SimObjects\Airplanes + static QSet fsxSimObjectsPaths(const QString &fsxFile, bool checked); + + //! .air file filter + static const QString airFileFilter(); + + private: + //! Utility functions + //! @{ + static QSet findP3dConfigFiles(const QString &configFile, const QString &versionHint = "v5"); + //! @} + + //! Log the reading of config files + static bool logConfigPathReading(); + }; + } // namespace + } // namespace +} // namespace + +#endif // guard diff --git a/src/blackmisc/simulation/settings/simulatorsettings.cpp b/src/blackmisc/simulation/settings/simulatorsettings.cpp index e650dacd6..b5dd2c82e 100644 --- a/src/blackmisc/simulation/settings/simulatorsettings.cpp +++ b/src/blackmisc/simulation/settings/simulatorsettings.cpp @@ -8,7 +8,7 @@ #include "simulatorsettings.h" #include "blackmisc/simulation/simulatedaircraft.h" -#include "blackmisc/simulation/fscommon/fscommonutil.h" +#include "blackmisc/simulation/fscommon/fsdirectories.h" #include "blackmisc/simulation/xplane/xplaneutil.h" #include "blackmisc/simulation/flightgear/flightgearutil.h" #include "blackmisc/verify.h" @@ -588,14 +588,14 @@ namespace BlackMisc switch (m_simulator.getSimulator()) { case CSimulatorInfo::FG: dirs = QStringList(CFlightgearUtil::modelDirectoriesFromSimDir(s)); break; - case CSimulatorInfo::FS9: dirs = QStringList({ CFsCommonUtil::fs9AircraftDirFromSimDir(s) }); break; + case CSimulatorInfo::FS9: dirs = QStringList({ CFsDirectories::fs9AircraftDirFromSimDir(s) }); break; case CSimulatorInfo::FSX: - dirs = CFsCommonUtil::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(CFsCommonUtil::fsxSimObjectsDirFromSimDir(s)); + dirs = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(CFsDirectories::fsxSimObjectsDirFromSimDir(s)); break; case CSimulatorInfo::P3D: { - const QString versionHint = CFsCommonUtil::guessP3DVersion(s); - dirs = CFsCommonUtil::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(CFsCommonUtil::p3dSimObjectsDirFromSimDir(s), versionHint); + const QString versionHint = CFsDirectories::guessP3DVersion(s); + dirs = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(CFsDirectories::p3dSimObjectsDirFromSimDir(s), versionHint); } break; case CSimulatorInfo::XPLANE: dirs = QStringList({CXPlaneUtil::modelDirectoriesFromSimDir(s)}); break; @@ -669,22 +669,22 @@ namespace BlackMisc } case CSimulatorInfo::FS9: { - if (CFsCommonUtil::fs9AircraftDir().isEmpty()) { return e; } - static const QStringList md({ CFsCommonUtil::fs9AircraftDir() }); + if (CFsDirectories::fs9AircraftDir().isEmpty()) { return e; } + static const QStringList md({ CFsDirectories::fs9AircraftDir() }); return md; } case CSimulatorInfo::FSX: { - if (CFsCommonUtil::fsxSimObjectsDir().isEmpty()) { return e; } - static const QStringList md = CFsCommonUtil::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(); + if (CFsDirectories::fsxSimObjectsDir().isEmpty()) { return e; } + static const QStringList md = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(); return md; } case CSimulatorInfo::P3D: { - static const QString p3d = CFsCommonUtil::p3dSimObjectsDir(); + static const QString p3d = CFsDirectories::p3dSimObjectsDir(); if (p3d.isEmpty()) { return e; } - static const QString versionHint = CFsCommonUtil::guessP3DVersion(p3d); - static const QStringList md = CFsCommonUtil::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(p3d, versionHint); + static const QString versionHint = CFsDirectories::guessP3DVersion(p3d); + static const QStringList md = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(p3d, versionHint); return md; } case CSimulatorInfo::XPLANE: @@ -705,9 +705,9 @@ namespace BlackMisc switch (simulator.getSimulator()) { case CSimulatorInfo::FG: return CFlightgearUtil::flightgearRootDir(); - case CSimulatorInfo::FS9: return CFsCommonUtil::fs9Dir(); - case CSimulatorInfo::FSX: return CFsCommonUtil::fsxDir(); - case CSimulatorInfo::P3D: return CFsCommonUtil::p3dDir(); + case CSimulatorInfo::FS9: return CFsDirectories::fs9Dir(); + case CSimulatorInfo::FSX: return CFsDirectories::fsxDir(); + case CSimulatorInfo::P3D: return CFsDirectories::p3dDir(); case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneRootDir(); default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); @@ -723,9 +723,9 @@ namespace BlackMisc switch (simulator.getSimulator()) { case CSimulatorInfo::FG: return CFlightgearUtil::flightgearModelExcludeDirectoryPatterns(); - case CSimulatorInfo::FS9: return CFsCommonUtil::fs9AircraftObjectsExcludeDirectoryPatterns(); - case CSimulatorInfo::FSX: return CFsCommonUtil::fsxSimObjectsExcludeDirectoryPatterns(); - case CSimulatorInfo::P3D: return CFsCommonUtil::p3dSimObjectsExcludeDirectoryPatterns(); + case CSimulatorInfo::FS9: return CFsDirectories::fs9AircraftObjectsExcludeDirectoryPatterns(); + case CSimulatorInfo::FSX: return CFsDirectories::fsxSimObjectsExcludeDirectoryPatterns(); + case CSimulatorInfo::P3D: return CFsDirectories::p3dSimObjectsExcludeDirectoryPatterns(); case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneModelExcludeDirectoryPatterns(); default: Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator"); diff --git a/src/blackmisc/simulation/simulatorinfo.cpp b/src/blackmisc/simulation/simulatorinfo.cpp index 7ef05f8e7..3a0384185 100644 --- a/src/blackmisc/simulation/simulatorinfo.cpp +++ b/src/blackmisc/simulation/simulatorinfo.cpp @@ -7,7 +7,7 @@ */ #include "blackconfig/buildconfig.h" -#include "blackmisc/simulation/fscommon/fscommonutil.h" +#include "blackmisc/simulation/fscommon/fsdirectories.h" #include "blackmisc/simulation/simulatorinfo.h" #include "blackmisc/simulation/xplane/xplaneutil.h" #include "blackmisc/db/datastoreutility.h" @@ -299,14 +299,14 @@ namespace BlackMisc if (CBuildConfig::isRunningOnWindowsNtPlatform()) { fs9 = - !CFsCommonUtil::fs9AircraftDir().isEmpty() && - !CFsCommonUtil::fs9Dir().isEmpty(); + !CFsDirectories::fs9AircraftDir().isEmpty() && + !CFsDirectories::fs9Dir().isEmpty(); fsx = - !CFsCommonUtil::fsxSimObjectsDir().isEmpty() && - !CFsCommonUtil::fsxDir().isEmpty(); + !CFsDirectories::fsxSimObjectsDir().isEmpty() && + !CFsDirectories::fsxDir().isEmpty(); p3d = - !CFsCommonUtil::p3dDir().isEmpty() && - !CFsCommonUtil::p3dSimObjectsDir().isEmpty(); + !CFsDirectories::p3dDir().isEmpty() && + !CFsDirectories::p3dSimObjectsDir().isEmpty(); } const bool xp = !CXPlaneUtil::xplaneRootDir().isEmpty(); diff --git a/src/swiftlauncher/swiftlauncher.cpp b/src/swiftlauncher/swiftlauncher.cpp index d93c486b4..659b381fa 100644 --- a/src/swiftlauncher/swiftlauncher.cpp +++ b/src/swiftlauncher/swiftlauncher.cpp @@ -16,7 +16,7 @@ #include "blackcore/context/contextapplicationproxy.h" #include "blackcore/setupreader.h" #include "blacksound/audioutilities.h" -#include "blackmisc/simulation/fscommon/fscommonutil.h" +#include "blackmisc/simulation/fscommon/fsdirectories.h" #include "blackcore/context/contextnetwork.h" #include "blackmisc/network/networkutils.h" #include "blackmisc/dbusserver.h" @@ -648,16 +648,16 @@ void CSwiftLauncher::showSimulatorConfigDirs() if (s == ui->pb_P3DConfigDirs) { - simDir = CFsCommonUtil::p3dDir(); - simObjDir = CFsCommonUtil::p3dSimObjectsDir(); - const QString versionHint = CFsCommonUtil::guessP3DVersion(simDir); - dirs = CFsCommonUtil::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(simObjDir, versionHint); + simDir = CFsDirectories::p3dDir(); + simObjDir = CFsDirectories::p3dSimObjectsDir(); + const QString versionHint = CFsDirectories::guessP3DVersion(simDir); + dirs = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(simObjDir, versionHint); } else if (s == ui->pb_FSXConfigDirs) { - dirs = CFsCommonUtil::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(); - simDir = CFsCommonUtil::fsxDir(); - simObjDir = CFsCommonUtil::fsxSimObjectsDir(); + dirs = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(); + simDir = CFsDirectories::fsxDir(); + simObjDir = CFsDirectories::fsxSimObjectsDir(); } const QString info = u"Sim.dir: " % simDir % "\n" %