mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-05-04 00:45:46 +08:00
Issue #77 Factor out parts of CFsCommonUtil into new class CFsDirectories
This breaks the cyclic dependency involving CSimulatorInfo, CFsCommonUtil, and CAircraftModelList.
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
//! \ingroup sampleblackmiscsim
|
//! \ingroup sampleblackmiscsim
|
||||||
|
|
||||||
#include "samplesp3d.h"
|
#include "samplesp3d.h"
|
||||||
#include "blackmisc/simulation/fscommon/fscommonutil.h"
|
#include "blackmisc/simulation/fscommon/fsdirectories.h"
|
||||||
#include "blackmisc/stringutils.h"
|
#include "blackmisc/stringutils.h"
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
|
|
||||||
@@ -20,15 +20,15 @@ namespace BlackSample
|
|||||||
{
|
{
|
||||||
void CSamplesP3D::samplesMisc(QTextStream &streamOut)
|
void CSamplesP3D::samplesMisc(QTextStream &streamOut)
|
||||||
{
|
{
|
||||||
QSet<QString> configFiles = CFsCommonUtil::findP3dAddOnConfigFiles("v5");
|
QSet<QString> configFiles = CFsDirectories::findP3dAddOnConfigFiles("v5");
|
||||||
if (configFiles.isEmpty()) { configFiles = CFsCommonUtil::findP3dAddOnConfigFiles("v4"); }
|
if (configFiles.isEmpty()) { configFiles = CFsDirectories::findP3dAddOnConfigFiles("v4"); }
|
||||||
|
|
||||||
streamOut << BlackMisc::joinStringSet(configFiles, ", ") << Qt::endl;
|
streamOut << BlackMisc::joinStringSet(configFiles, ", ") << Qt::endl;
|
||||||
|
|
||||||
const QSet<QString> addOnPaths = CFsCommonUtil::allConfigFilesPathValues(configFiles.values(), false, {});
|
const QSet<QString> addOnPaths = CFsDirectories::allConfigFilesPathValues(configFiles.values(), false, {});
|
||||||
streamOut << BlackMisc::joinStringSet(addOnPaths, ", ") << Qt::endl;
|
streamOut << BlackMisc::joinStringSet(addOnPaths, ", ") << Qt::endl;
|
||||||
|
|
||||||
const QSet<QString> simObjectPaths = CFsCommonUtil::fsxSimObjectsPaths("B:/fsx.cfg", false);
|
const QSet<QString> simObjectPaths = CFsDirectories::fsxSimObjectsPaths("B:/fsx.cfg", false);
|
||||||
streamOut << BlackMisc::joinStringSet(simObjectPaths, ", ") << Qt::endl;
|
streamOut << BlackMisc::joinStringSet(simObjectPaths, ", ") << Qt::endl;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "configsimulatorcomponent.h"
|
#include "configsimulatorcomponent.h"
|
||||||
#include "blackgui/guiutility.h"
|
#include "blackgui/guiutility.h"
|
||||||
#include "blackmisc/logmessage.h"
|
#include "blackmisc/logmessage.h"
|
||||||
#include "blackmisc/simulation/fscommon/fscommonutil.h"
|
#include "blackmisc/simulation/fscommon/fsdirectories.h"
|
||||||
#include "blackconfig/buildconfig.h"
|
#include "blackconfig/buildconfig.h"
|
||||||
#include "ui_configsimulatorcomponent.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
|
// 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 p3d = (sims.isP3D() || !CFsDirectories::p3dDir().isEmpty()) && CBuildConfig::isCompiledWithP3DSupport();
|
||||||
const bool fsx = (sims.isFSX() || !CFsCommonUtil::fsxDir().isEmpty()) && CBuildConfig::isCompiledWithFsxSupport();
|
const bool fsx = (sims.isFSX() || !CFsDirectories::fsxDir().isEmpty()) && CBuildConfig::isCompiledWithFsxSupport();
|
||||||
const bool fs9 = (sims.isFS9() || !CFsCommonUtil::fs9Dir().isEmpty()) && CBuildConfig::isCompiledWithFs9Support();
|
const bool fs9 = (sims.isFS9() || !CFsDirectories::fs9Dir().isEmpty()) && CBuildConfig::isCompiledWithFs9Support();
|
||||||
const bool xp = sims.isXPlane() && CBuildConfig::isCompiledWithXPlaneSupport();
|
const bool xp = sims.isXPlane() && CBuildConfig::isCompiledWithXPlaneSupport();
|
||||||
const bool fg = sims.isFG() && CBuildConfig::isCompiledWithFGSupport();
|
const bool fg = sims.isFG() && CBuildConfig::isCompiledWithFGSupport();
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "blackmisc/simulation/fscommon/aircraftcfgentries.h"
|
#include "blackmisc/simulation/fscommon/aircraftcfgentries.h"
|
||||||
#include "blackmisc/simulation/fscommon/aircraftcfgparser.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/fileutils.h"
|
||||||
#include "blackmisc/logmessage.h"
|
#include "blackmisc/logmessage.h"
|
||||||
#include "blackmisc/statusmessagelist.h"
|
#include "blackmisc/statusmessagelist.h"
|
||||||
@@ -176,7 +176,7 @@ namespace BlackMisc
|
|||||||
|
|
||||||
// the sim.cfg/aircraft.cfg file should have an *.air file sibling
|
// the sim.cfg/aircraft.cfg file should have an *.air file sibling
|
||||||
// if not we assume these files can be ignored
|
// 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 int airFilesCount = dirForAir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot, QDir::DirsLast).size();
|
||||||
const bool hasAirFiles = airFilesCount > 0;
|
const bool hasAirFiles = airFilesCount > 0;
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,9 @@
|
|||||||
* or distributed except according to the terms contained in the LICENSE file.
|
* or distributed except according to the terms contained in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "fscommonutil.h"
|
#include "blackmisc/simulation/fscommon/fscommonutil.h"
|
||||||
#include "aircraftcfgparser.h"
|
#include "blackmisc/simulation/fscommon/fsdirectories.h"
|
||||||
|
#include "blackmisc/simulation/fscommon/aircraftcfgparser.h"
|
||||||
#include "blackmisc/swiftdirectories.h"
|
#include "blackmisc/swiftdirectories.h"
|
||||||
#include "blackmisc/directoryutils.h"
|
#include "blackmisc/directoryutils.h"
|
||||||
#include "blackmisc/fileutils.h"
|
#include "blackmisc/fileutils.h"
|
||||||
@@ -37,353 +38,12 @@ namespace BlackMisc
|
|||||||
{
|
{
|
||||||
namespace FsCommon
|
namespace FsCommon
|
||||||
{
|
{
|
||||||
using FsRegistryPathPair = QList<QPair<QString, QString>>;
|
|
||||||
|
|
||||||
const QStringList &CFsCommonUtil::getLogCategories()
|
const QStringList &CFsCommonUtil::getLogCategories()
|
||||||
{
|
{
|
||||||
static const QStringList cats({ CLogCategories::validation(), CLogCategories::driver() });
|
static const QStringList cats({ CLogCategories::validation(), CLogCategories::driver() });
|
||||||
return cats;
|
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)
|
bool CFsCommonUtil::adjustFileDirectory(CAircraftModel &model, const QString &simObjectsDirectory)
|
||||||
{
|
{
|
||||||
if (model.hasExistingCorrespondingFile()) { return true; }
|
if (model.hasExistingCorrespondingFile()) { return true; }
|
||||||
@@ -453,208 +113,6 @@ namespace BlackMisc
|
|||||||
return copied;
|
return copied;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<QString> CFsCommonUtil::findP3dAddOnConfigFiles(const QString &versionHint)
|
|
||||||
{
|
|
||||||
static const QString cfgFile("add-ons.cfg");
|
|
||||||
return CFsCommonUtil::findP3dConfigFiles(cfgFile, versionHint);
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> CFsCommonUtil::findP3dSimObjectsConfigFiles(const QString &versionHint)
|
|
||||||
{
|
|
||||||
static const QString cfgFile("simobjects.cfg");
|
|
||||||
return CFsCommonUtil::findP3dConfigFiles(cfgFile, versionHint);
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> 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<QString> 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<CFsCommonUtil *>(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<CFsCommonUtil *>(nullptr)).info(u"P3D config file: '%1'") << f; }
|
|
||||||
}
|
|
||||||
} // contains
|
|
||||||
} // entries
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> CFsCommonUtil::allConfigFilesPathValues(const QStringList &configFiles, bool checked, const QString &pathPrefix)
|
|
||||||
{
|
|
||||||
if (configFiles.isEmpty()) { return QSet<QString>(); }
|
|
||||||
QSet<QString> 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<QStringRef> 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<QString> CFsCommonUtil::allP3dAddOnXmlSimObjectPaths(const QStringList &addOnPaths, bool checked)
|
|
||||||
{
|
|
||||||
if (addOnPaths.isEmpty()) { return QSet<QString>(); }
|
|
||||||
QSet<QString> 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<CFsCommonUtil *>(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<CFsCommonUtil *>(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<CFsCommonUtil *>(nullptr)).info(u"P3D SimObjects path: '%1'") << fp; }
|
|
||||||
}
|
|
||||||
} // components
|
|
||||||
} // paths
|
|
||||||
|
|
||||||
return simObjectPaths;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> 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<QString> all = CFsCommonUtil::allP3dAddOnXmlSimObjectPaths(addOnPaths, true);
|
|
||||||
return all;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> 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<CFsCommonUtil *>(nullptr)).info(u"FSX config file: '%1'") << fi.absoluteFilePath(); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> CFsCommonUtil::fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked)
|
|
||||||
{
|
|
||||||
QSet<QString> paths;
|
|
||||||
for (const QString &fsxFile : fsxFiles)
|
|
||||||
{
|
|
||||||
paths.unite(CFsCommonUtil::fsxSimObjectsPaths(fsxFile, checked));
|
|
||||||
}
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> CFsCommonUtil::fsxSimObjectsPaths(const QString &fsxFile, bool checked)
|
|
||||||
{
|
|
||||||
const QString fileContent = CFileUtils::readFileToString(fsxFile);
|
|
||||||
if (fileContent.isEmpty()) { return QSet<QString>(); }
|
|
||||||
const QList<QStringRef> lines = splitLinesRefs(fileContent);
|
|
||||||
static const QString p("SimObjectPaths.");
|
|
||||||
|
|
||||||
const QFileInfo fsxFileInfo(fsxFile);
|
|
||||||
const QString relPath = fsxFileInfo.absolutePath();
|
|
||||||
|
|
||||||
QSet<QString> 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<CFsCommonUtil *>(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<CFsCommonUtil *>(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<CFsCommonUtil *>(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<CFsCommonUtil *>(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)
|
CStatusMessageList CFsCommonUtil::validateAircraftConfigFiles(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &wasStopped)
|
||||||
{
|
{
|
||||||
CStatusMessage m;
|
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)
|
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 QString simObjectsDir = simulatorDir.isEmpty() ? CFsDirectories::p3dSimObjectsDir() : CFsDirectories::p3dSimObjectsDirFromSimDir(simulatorDir);
|
||||||
const QStringList simObjectPaths = CFsCommonUtil::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(simObjectsDir, guessP3DVersion(simObjectsDir));
|
const QStringList simObjectPaths = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(simObjectsDir, CFsDirectories::guessP3DVersion(simObjectsDir));
|
||||||
return CFsCommonUtil::validateSimObjectsPath(QSet<QString>(simObjectPaths.begin(), simObjectPaths.end()), models, validModels, invalidModels, ignoreEmptyFileNames, stopAtFailedFiles, wasStopped);
|
return CFsCommonUtil::validateSimObjectsPath(QSet<QString>(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)
|
CStatusMessageList CFsCommonUtil::validateFSXSimObjectsPath(const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &stopped, const QString &simulatorDir)
|
||||||
{
|
{
|
||||||
Q_UNUSED(simulatorDir)
|
Q_UNUSED(simulatorDir)
|
||||||
const QStringList simObjectPaths = CFsCommonUtil::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths();
|
const QStringList simObjectPaths = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths();
|
||||||
return CFsCommonUtil::validateSimObjectsPath(QSet<QString>(simObjectPaths.begin(), simObjectPaths.end()), models, validModels, invalidModels, ignoreEmptyFileNames, stopAtFailedFiles, stopped);
|
return CFsCommonUtil::validateSimObjectsPath(QSet<QString>(simObjectPaths.begin(), simObjectPaths.end()), models, validModels, invalidModels, ignoreEmptyFileNames, stopAtFailedFiles, stopped);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString CFsCommonUtil::airFileFilter()
|
|
||||||
{
|
|
||||||
static const QString a("*.air");
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
CStatusMessageList CFsCommonUtil::validateSimObjectsPath(
|
CStatusMessageList CFsCommonUtil::validateSimObjectsPath(
|
||||||
const QSet<QString> &simObjectDirs, const CAircraftModelList &models,
|
const QSet<QString> &simObjectDirs, const CAircraftModelList &models,
|
||||||
CAircraftModelList &validModels, CAircraftModelList &invalidModels,
|
CAircraftModelList &validModels, CAircraftModelList &invalidModels,
|
||||||
@@ -799,11 +251,6 @@ namespace BlackMisc
|
|||||||
|
|
||||||
return msgs;
|
return msgs;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CFsCommonUtil::logConfigPathReading()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -35,69 +35,6 @@ namespace BlackMisc
|
|||||||
//! Constructor
|
//! Constructor
|
||||||
CFsCommonUtil() = delete;
|
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
|
//! Adjust file directory
|
||||||
static bool adjustFileDirectory(CAircraftModel &model, const QString &simObjectsDirectory);
|
static bool adjustFileDirectory(CAircraftModel &model, const QString &simObjectsDirectory);
|
||||||
|
|
||||||
@@ -107,40 +44,6 @@ namespace BlackMisc
|
|||||||
//! Copy the terrain probe
|
//! Copy the terrain probe
|
||||||
static int copyFsxTerrainProbeFiles(const QString &simObjectDir, CStatusMessageList &messages);
|
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<QString> 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<QString> findP3dSimObjectsConfigFiles(const QString &versionHint = "v5");
|
|
||||||
|
|
||||||
//! All PATH values from the config files
|
|
||||||
static QSet<QString> allConfigFilesPathValues(const QStringList &configFiles, bool checked, const QString &pathPrefix);
|
|
||||||
|
|
||||||
//! All add-on paths from the XML add-on files "add-on.xml"
|
|
||||||
static QSet<QString> 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<QString> allP3dAddOnXmlSimObjectPaths(const QString &versionHint = "v4");
|
|
||||||
|
|
||||||
//! Get all the SimObjects paths from all config files
|
|
||||||
static QSet<QString> 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<QString> fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked);
|
|
||||||
|
|
||||||
//! Get all the SimObjects files from fsx.cfg
|
|
||||||
// SimObjectPaths.0=SimObjects\Airplanes
|
|
||||||
static QSet<QString> fsxSimObjectsPaths(const QString &fsxFile, bool checked);
|
|
||||||
|
|
||||||
//! Validate aircraft.cfg entries (sometimes also sim.cfg)
|
//! Validate aircraft.cfg entries (sometimes also sim.cfg)
|
||||||
//! \remark only for FSX/P3D/FS9 models
|
//! \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);
|
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
|
//! \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);
|
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:
|
private:
|
||||||
//! Utility functions
|
|
||||||
//! @{
|
|
||||||
static QSet<QString> findP3dConfigFiles(const QString &configFile, const QString &versionHint = "v5");
|
|
||||||
//! @}
|
|
||||||
|
|
||||||
//! Validate if known SimObjects path are used
|
//! Validate if known SimObjects path are used
|
||||||
//! \remark only for P3D/FSX
|
//! \remark only for P3D/FSX
|
||||||
static CStatusMessageList validateSimObjectsPath(const QSet<QString> &simObjectDirs, const CAircraftModelList &models, CAircraftModelList &validModels, CAircraftModelList &invalidModels, bool ignoreEmptyFileNames, int stopAtFailedFiles, std::atomic_bool &stopped);
|
static CStatusMessageList validateSimObjectsPath(const QSet<QString> &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
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
600
src/blackmisc/simulation/fscommon/fsdirectories.cpp
Normal file
600
src/blackmisc/simulation/fscommon/fsdirectories.cpp
Normal file
@@ -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 <QDir>
|
||||||
|
#include <QList>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QDomDocument>
|
||||||
|
#include <QDomNodeList>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QStringBuilder>
|
||||||
|
|
||||||
|
using namespace BlackConfig;
|
||||||
|
|
||||||
|
namespace BlackMisc
|
||||||
|
{
|
||||||
|
namespace Simulation
|
||||||
|
{
|
||||||
|
namespace FsCommon
|
||||||
|
{
|
||||||
|
using FsRegistryPathPair = QList<QPair<QString, QString>>;
|
||||||
|
|
||||||
|
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<QString> CFsDirectories::findP3dAddOnConfigFiles(const QString &versionHint)
|
||||||
|
{
|
||||||
|
static const QString cfgFile("add-ons.cfg");
|
||||||
|
return CFsDirectories::findP3dConfigFiles(cfgFile, versionHint);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QString> CFsDirectories::findP3dSimObjectsConfigFiles(const QString &versionHint)
|
||||||
|
{
|
||||||
|
static const QString cfgFile("simobjects.cfg");
|
||||||
|
return CFsDirectories::findP3dConfigFiles(cfgFile, versionHint);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QString> 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<QString> 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<CFsDirectories *>(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<CFsDirectories *>(nullptr)).info(u"P3D config file: '%1'") << f; }
|
||||||
|
}
|
||||||
|
} // contains
|
||||||
|
} // entries
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QString> CFsDirectories::allConfigFilesPathValues(const QStringList &configFiles, bool checked, const QString &pathPrefix)
|
||||||
|
{
|
||||||
|
if (configFiles.isEmpty()) { return QSet<QString>(); }
|
||||||
|
QSet<QString> 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<QStringRef> 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<QString> CFsDirectories::allP3dAddOnXmlSimObjectPaths(const QStringList &addOnPaths, bool checked)
|
||||||
|
{
|
||||||
|
if (addOnPaths.isEmpty()) { return QSet<QString>(); }
|
||||||
|
QSet<QString> 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<CFsDirectories *>(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<CFsDirectories *>(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<CFsDirectories *>(nullptr)).info(u"P3D SimObjects path: '%1'") << fp; }
|
||||||
|
}
|
||||||
|
} // components
|
||||||
|
} // paths
|
||||||
|
|
||||||
|
return simObjectPaths;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QString> 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<QString> all = CFsDirectories::allP3dAddOnXmlSimObjectPaths(addOnPaths, true);
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QString> 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<CFsDirectories *>(nullptr)).info(u"FSX config file: '%1'") << fi.absoluteFilePath(); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QString> CFsDirectories::fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked)
|
||||||
|
{
|
||||||
|
QSet<QString> paths;
|
||||||
|
for (const QString &fsxFile : fsxFiles)
|
||||||
|
{
|
||||||
|
paths.unite(CFsDirectories::fsxSimObjectsPaths(fsxFile, checked));
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<QString> CFsDirectories::fsxSimObjectsPaths(const QString &fsxFile, bool checked)
|
||||||
|
{
|
||||||
|
const QString fileContent = CFileUtils::readFileToString(fsxFile);
|
||||||
|
if (fileContent.isEmpty()) { return QSet<QString>(); }
|
||||||
|
const QList<QStringRef> lines = splitLinesRefs(fileContent);
|
||||||
|
static const QString p("SimObjectPaths.");
|
||||||
|
|
||||||
|
const QFileInfo fsxFileInfo(fsxFile);
|
||||||
|
const QString relPath = fsxFileInfo.absolutePath();
|
||||||
|
|
||||||
|
QSet<QString> 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<CFsDirectories *>(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<CFsDirectories *>(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<CFsDirectories *>(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<CFsDirectories *>(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
|
||||||
150
src/blackmisc/simulation/fscommon/fsdirectories.h
Normal file
150
src/blackmisc/simulation/fscommon/fsdirectories.h
Normal file
@@ -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 <atomic>
|
||||||
|
#include <QSet>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
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<QString> 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<QString> findP3dSimObjectsConfigFiles(const QString &versionHint = "v5");
|
||||||
|
|
||||||
|
//! All PATH values from the config files
|
||||||
|
static QSet<QString> allConfigFilesPathValues(const QStringList &configFiles, bool checked, const QString &pathPrefix);
|
||||||
|
|
||||||
|
//! All add-on paths from the XML add-on files "add-on.xml"
|
||||||
|
static QSet<QString> 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<QString> allP3dAddOnXmlSimObjectPaths(const QString &versionHint = "v4");
|
||||||
|
|
||||||
|
//! Get all the SimObjects paths from all config files
|
||||||
|
static QSet<QString> 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<QString> fsxSimObjectsPaths(const QStringList &fsxFiles, bool checked);
|
||||||
|
|
||||||
|
//! Get all the SimObjects files from fsx.cfg
|
||||||
|
// SimObjectPaths.0=SimObjects\Airplanes
|
||||||
|
static QSet<QString> fsxSimObjectsPaths(const QString &fsxFile, bool checked);
|
||||||
|
|
||||||
|
//! .air file filter
|
||||||
|
static const QString airFileFilter();
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! Utility functions
|
||||||
|
//! @{
|
||||||
|
static QSet<QString> findP3dConfigFiles(const QString &configFile, const QString &versionHint = "v5");
|
||||||
|
//! @}
|
||||||
|
|
||||||
|
//! Log the reading of config files
|
||||||
|
static bool logConfigPathReading();
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
} // namespace
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif // guard
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "simulatorsettings.h"
|
#include "simulatorsettings.h"
|
||||||
#include "blackmisc/simulation/simulatedaircraft.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/xplane/xplaneutil.h"
|
||||||
#include "blackmisc/simulation/flightgear/flightgearutil.h"
|
#include "blackmisc/simulation/flightgear/flightgearutil.h"
|
||||||
#include "blackmisc/verify.h"
|
#include "blackmisc/verify.h"
|
||||||
@@ -588,14 +588,14 @@ namespace BlackMisc
|
|||||||
switch (m_simulator.getSimulator())
|
switch (m_simulator.getSimulator())
|
||||||
{
|
{
|
||||||
case CSimulatorInfo::FG: dirs = QStringList(CFlightgearUtil::modelDirectoriesFromSimDir(s)); break;
|
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:
|
case CSimulatorInfo::FSX:
|
||||||
dirs = CFsCommonUtil::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(CFsCommonUtil::fsxSimObjectsDirFromSimDir(s));
|
dirs = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths(CFsDirectories::fsxSimObjectsDirFromSimDir(s));
|
||||||
break;
|
break;
|
||||||
case CSimulatorInfo::P3D:
|
case CSimulatorInfo::P3D:
|
||||||
{
|
{
|
||||||
const QString versionHint = CFsCommonUtil::guessP3DVersion(s);
|
const QString versionHint = CFsDirectories::guessP3DVersion(s);
|
||||||
dirs = CFsCommonUtil::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(CFsCommonUtil::p3dSimObjectsDirFromSimDir(s), versionHint);
|
dirs = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(CFsDirectories::p3dSimObjectsDirFromSimDir(s), versionHint);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CSimulatorInfo::XPLANE: dirs = QStringList({CXPlaneUtil::modelDirectoriesFromSimDir(s)}); break;
|
case CSimulatorInfo::XPLANE: dirs = QStringList({CXPlaneUtil::modelDirectoriesFromSimDir(s)}); break;
|
||||||
@@ -669,22 +669,22 @@ namespace BlackMisc
|
|||||||
}
|
}
|
||||||
case CSimulatorInfo::FS9:
|
case CSimulatorInfo::FS9:
|
||||||
{
|
{
|
||||||
if (CFsCommonUtil::fs9AircraftDir().isEmpty()) { return e; }
|
if (CFsDirectories::fs9AircraftDir().isEmpty()) { return e; }
|
||||||
static const QStringList md({ CFsCommonUtil::fs9AircraftDir() });
|
static const QStringList md({ CFsDirectories::fs9AircraftDir() });
|
||||||
return md;
|
return md;
|
||||||
}
|
}
|
||||||
case CSimulatorInfo::FSX:
|
case CSimulatorInfo::FSX:
|
||||||
{
|
{
|
||||||
if (CFsCommonUtil::fsxSimObjectsDir().isEmpty()) { return e; }
|
if (CFsDirectories::fsxSimObjectsDir().isEmpty()) { return e; }
|
||||||
static const QStringList md = CFsCommonUtil::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths();
|
static const QStringList md = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths();
|
||||||
return md;
|
return md;
|
||||||
}
|
}
|
||||||
case CSimulatorInfo::P3D:
|
case CSimulatorInfo::P3D:
|
||||||
{
|
{
|
||||||
static const QString p3d = CFsCommonUtil::p3dSimObjectsDir();
|
static const QString p3d = CFsDirectories::p3dSimObjectsDir();
|
||||||
if (p3d.isEmpty()) { return e; }
|
if (p3d.isEmpty()) { return e; }
|
||||||
static const QString versionHint = CFsCommonUtil::guessP3DVersion(p3d);
|
static const QString versionHint = CFsDirectories::guessP3DVersion(p3d);
|
||||||
static const QStringList md = CFsCommonUtil::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(p3d, versionHint);
|
static const QStringList md = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(p3d, versionHint);
|
||||||
return md;
|
return md;
|
||||||
}
|
}
|
||||||
case CSimulatorInfo::XPLANE:
|
case CSimulatorInfo::XPLANE:
|
||||||
@@ -705,9 +705,9 @@ namespace BlackMisc
|
|||||||
switch (simulator.getSimulator())
|
switch (simulator.getSimulator())
|
||||||
{
|
{
|
||||||
case CSimulatorInfo::FG: return CFlightgearUtil::flightgearRootDir();
|
case CSimulatorInfo::FG: return CFlightgearUtil::flightgearRootDir();
|
||||||
case CSimulatorInfo::FS9: return CFsCommonUtil::fs9Dir();
|
case CSimulatorInfo::FS9: return CFsDirectories::fs9Dir();
|
||||||
case CSimulatorInfo::FSX: return CFsCommonUtil::fsxDir();
|
case CSimulatorInfo::FSX: return CFsDirectories::fsxDir();
|
||||||
case CSimulatorInfo::P3D: return CFsCommonUtil::p3dDir();
|
case CSimulatorInfo::P3D: return CFsDirectories::p3dDir();
|
||||||
case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneRootDir();
|
case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneRootDir();
|
||||||
default:
|
default:
|
||||||
Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
|
Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
|
||||||
@@ -723,9 +723,9 @@ namespace BlackMisc
|
|||||||
switch (simulator.getSimulator())
|
switch (simulator.getSimulator())
|
||||||
{
|
{
|
||||||
case CSimulatorInfo::FG: return CFlightgearUtil::flightgearModelExcludeDirectoryPatterns();
|
case CSimulatorInfo::FG: return CFlightgearUtil::flightgearModelExcludeDirectoryPatterns();
|
||||||
case CSimulatorInfo::FS9: return CFsCommonUtil::fs9AircraftObjectsExcludeDirectoryPatterns();
|
case CSimulatorInfo::FS9: return CFsDirectories::fs9AircraftObjectsExcludeDirectoryPatterns();
|
||||||
case CSimulatorInfo::FSX: return CFsCommonUtil::fsxSimObjectsExcludeDirectoryPatterns();
|
case CSimulatorInfo::FSX: return CFsDirectories::fsxSimObjectsExcludeDirectoryPatterns();
|
||||||
case CSimulatorInfo::P3D: return CFsCommonUtil::p3dSimObjectsExcludeDirectoryPatterns();
|
case CSimulatorInfo::P3D: return CFsDirectories::p3dSimObjectsExcludeDirectoryPatterns();
|
||||||
case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneModelExcludeDirectoryPatterns();
|
case CSimulatorInfo::XPLANE: return CXPlaneUtil::xplaneModelExcludeDirectoryPatterns();
|
||||||
default:
|
default:
|
||||||
Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
|
Q_ASSERT_X(simulator.isSingleSimulator(), Q_FUNC_INFO, "No single simulator");
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "blackconfig/buildconfig.h"
|
#include "blackconfig/buildconfig.h"
|
||||||
#include "blackmisc/simulation/fscommon/fscommonutil.h"
|
#include "blackmisc/simulation/fscommon/fsdirectories.h"
|
||||||
#include "blackmisc/simulation/simulatorinfo.h"
|
#include "blackmisc/simulation/simulatorinfo.h"
|
||||||
#include "blackmisc/simulation/xplane/xplaneutil.h"
|
#include "blackmisc/simulation/xplane/xplaneutil.h"
|
||||||
#include "blackmisc/db/datastoreutility.h"
|
#include "blackmisc/db/datastoreutility.h"
|
||||||
@@ -299,14 +299,14 @@ namespace BlackMisc
|
|||||||
if (CBuildConfig::isRunningOnWindowsNtPlatform())
|
if (CBuildConfig::isRunningOnWindowsNtPlatform())
|
||||||
{
|
{
|
||||||
fs9 =
|
fs9 =
|
||||||
!CFsCommonUtil::fs9AircraftDir().isEmpty() &&
|
!CFsDirectories::fs9AircraftDir().isEmpty() &&
|
||||||
!CFsCommonUtil::fs9Dir().isEmpty();
|
!CFsDirectories::fs9Dir().isEmpty();
|
||||||
fsx =
|
fsx =
|
||||||
!CFsCommonUtil::fsxSimObjectsDir().isEmpty() &&
|
!CFsDirectories::fsxSimObjectsDir().isEmpty() &&
|
||||||
!CFsCommonUtil::fsxDir().isEmpty();
|
!CFsDirectories::fsxDir().isEmpty();
|
||||||
p3d =
|
p3d =
|
||||||
!CFsCommonUtil::p3dDir().isEmpty() &&
|
!CFsDirectories::p3dDir().isEmpty() &&
|
||||||
!CFsCommonUtil::p3dSimObjectsDir().isEmpty();
|
!CFsDirectories::p3dSimObjectsDir().isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool xp = !CXPlaneUtil::xplaneRootDir().isEmpty();
|
const bool xp = !CXPlaneUtil::xplaneRootDir().isEmpty();
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
#include "blackcore/context/contextapplicationproxy.h"
|
#include "blackcore/context/contextapplicationproxy.h"
|
||||||
#include "blackcore/setupreader.h"
|
#include "blackcore/setupreader.h"
|
||||||
#include "blacksound/audioutilities.h"
|
#include "blacksound/audioutilities.h"
|
||||||
#include "blackmisc/simulation/fscommon/fscommonutil.h"
|
#include "blackmisc/simulation/fscommon/fsdirectories.h"
|
||||||
#include "blackcore/context/contextnetwork.h"
|
#include "blackcore/context/contextnetwork.h"
|
||||||
#include "blackmisc/network/networkutils.h"
|
#include "blackmisc/network/networkutils.h"
|
||||||
#include "blackmisc/dbusserver.h"
|
#include "blackmisc/dbusserver.h"
|
||||||
@@ -648,16 +648,16 @@ void CSwiftLauncher::showSimulatorConfigDirs()
|
|||||||
|
|
||||||
if (s == ui->pb_P3DConfigDirs)
|
if (s == ui->pb_P3DConfigDirs)
|
||||||
{
|
{
|
||||||
simDir = CFsCommonUtil::p3dDir();
|
simDir = CFsDirectories::p3dDir();
|
||||||
simObjDir = CFsCommonUtil::p3dSimObjectsDir();
|
simObjDir = CFsDirectories::p3dSimObjectsDir();
|
||||||
const QString versionHint = CFsCommonUtil::guessP3DVersion(simDir);
|
const QString versionHint = CFsDirectories::guessP3DVersion(simDir);
|
||||||
dirs = CFsCommonUtil::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(simObjDir, versionHint);
|
dirs = CFsDirectories::p3dSimObjectsDirPlusAddOnXmlSimObjectsPaths(simObjDir, versionHint);
|
||||||
}
|
}
|
||||||
else if (s == ui->pb_FSXConfigDirs)
|
else if (s == ui->pb_FSXConfigDirs)
|
||||||
{
|
{
|
||||||
dirs = CFsCommonUtil::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths();
|
dirs = CFsDirectories::fsxSimObjectsDirPlusAddOnXmlSimObjectsPaths();
|
||||||
simDir = CFsCommonUtil::fsxDir();
|
simDir = CFsDirectories::fsxDir();
|
||||||
simObjDir = CFsCommonUtil::fsxSimObjectsDir();
|
simObjDir = CFsDirectories::fsxSimObjectsDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString info = u"Sim.dir: " % simDir % "\n" %
|
const QString info = u"Sim.dir: " % simDir % "\n" %
|
||||||
|
|||||||
Reference in New Issue
Block a user