13 #include <QFileInfoList>
19 #include <QStringView>
20 #include <QTextStream>
33 using namespace swift::config;
35 using namespace swift::misc::simulation;
36 using namespace swift::misc::simulation::fscommon;
37 using namespace swift::misc::network;
39 namespace swift::misc::simulation::fscommon
42 using LoaderResponse = std::tuple<CAircraftCfgEntriesList, CAircraftModelList, CStatusMessageList>;
56 if (m_parserWorker) { m_parserWorker->waitForFinished(); }
63 u
"Aircraft config parser loaded data");
65 u
"Aircraft config parser did NOT load data");
74 if (m_parserWorker && !m_parserWorker->isFinished()) {
return; }
78 [
this, modelDirs, excludedDirectoryPatterns, simulator, modelConsolidation]() {
81 this->performParsing(modelDirs, excludedDirectoryPatterns, msgs);
86 if (modelConsolidation) { modelConsolidation(models,
true); }
88 return std::make_tuple(aircraftCfgEntriesList, models, msgs);
90 m_parserWorker->thenWithResult<LoaderResponse>(
this, [
this, simulator](
const LoaderResponse &tuple) {
94 m_parsedCfgEntriesList = std::get<0>(tuple);
96 const bool hasData = !models.
isEmpty();
110 m_parsedCfgEntriesList = this->performParsing(modelDirs, excludedDirectoryPatterns, msgs);
114 const bool hasData = !models.
isEmpty();
128 for (
const QString &dir : directories)
130 entries.
push_back(this->performParsing(dir, excludeDirectories, messages));
154 static const QString NoNameFilter;
166 const QString currentDir = dir.absolutePath();
172 const QFileInfoList files =
180 const bool hasAirFiles = airFilesCount > 0;
188 for (
const auto &fileInfo : files)
191 if (fileInfo.isDir())
193 const QString nextDir = fileInfo.absoluteFilePath();
195 if (dir == currentDir) {
continue; }
208 if (
getSimulator().isP3D() && !hasAirFiles) {
continue; }
214 const QString fileName = fileInfo.absoluteFilePath();
263 QString fltSection(
"[FLTSIM.0]");
264 static const QString fltSectionStr(
"[FLTSIM.%1]");
266 int fltsimCounter = 0;
267 FileSection currentSection = Unknown;
273 if (lineFixed.
isEmpty()) {
continue; }
278 currentSection = General;
286 currentSection = Fltsim;
287 fltSection = fltSectionStr.
arg(++fltsimCounter);
290 currentSection = Unknown;
293 switch (currentSection)
300 const QString c = getFixedIniLineContent(lineFixed);
337 bool r = getFixedIniLineContent(lineFixed).
toLower().
contains(
"rotor");
342 e.
setUiType(getFixedIniLineContent(lineFixed));
355 e.
setTexture(getFixedIniLineContent(lineFixed));
363 e.
setSimName(getFixedIniLineContent(lineFixed));
367 e.
setTitle(getFixedIniLineContent(lineFixed));
381 Q_ASSERT_X(fileTimestamp.
isValid(), Q_FUNC_INFO,
"Missing file timestamp");
386 if (e.getTitle().isEmpty())
389 .
info(u
"FS model in %1, index %2 has no title")
390 << fileName << e.getIndex();
406 return fixedStringContent(settings.
value(key));
425 QString CAircraftCfgParser::getFixedIniLineContent(
const QString &line)
427 if (line.
isEmpty()) {
return {}; }
430 const int indexComment = line.
indexOf(
';');
433 const int index = line.
indexOf(
'=');
434 if (index < 0) {
return {}; }
435 if (line.
length() < index + 1) {
return {}; }
471 const QStringList &CAircraftCfgParser::fileNameFilters(
bool isMSFS,
bool isMSFS2024)
473 if (CBuildConfig::buildWordSize() == 32 || isMSFS || isMSFS2024)
480 static const QStringList f({
"aircraft.cfg",
"sim.cfg" });
485 bool CAircraftCfgParser::isExcludedSubDirectory(
const QString &checkDirectory)
487 if (checkDirectory.
isEmpty()) {
return false; }
489 if (dir == u
"texture" || dir.
startsWith(
"texture.")) {
return true; }
490 if (dir == u
"sound" || dir ==
"soundai") {
return true; }
491 if (dir == u
"panel") {
return true; }
492 if (dir == u
"model") {
return true; }
497 Q_DECLARE_METATYPE(swift::misc::simulation::fscommon::LoaderResponse)
static QString lastPathSegment(const QString &path)
Last path segment a/b/c => c.
static QString fixWindowsUncPath(const QString &filePath)
UNC file paths on Qt start with "/", but UNC file paths only work when they start with "//".
static bool isExcludedDirectory(const QDir &directory, const QStringList &excludeDirectories, Qt::CaseSensitivity cs=osFileNameCaseSensitivity())
Directory to be excluded?
Derived & warning(const char16_t(&format)[N])
Set the severity to warning, providing a format string.
Derived & info(const char16_t(&format)[N])
Set the severity to info, providing a format string.
void push_back(const T &value)
Appends an element at the end of the sequence.
void push_front(const T &value)
Insert as first element.
bool isEmpty() const
Synonym for empty.
Streamable status message, e.g.
constexpr static auto SeverityError
Status severities.
constexpr static auto SeverityInfo
Status severities.
Status messages, e.g. from Core -> GUI.
bool isSuccess() const
All messages are marked as success.
static CWorker * fromTask(QObject *owner, const QString &name, F &&task)
Returns a new worker object which lives in a new thread.
void freezeOrder()
Current order of list will be new order values.
void setUtcTimestamp(const QDateTime ×tamp)
Set timestamp.
Value object encapsulating a list of aircraft models.
Simple hardcoded info about the corresponding simulator.
Load the aircraft for a simulator.
void loadingProgress(const CSimulatorInfo &simulator, const QString &message, int progressPercentage)
Loading progress, normally from disk.
std::function< int(swift::misc::simulation::CAircraftModelList &, bool)> ModelConsolidationCallback
Callback to consolidate data, normally with DB data.
std::atomic< bool > m_cancelLoading
flag, requesting to cancel loading
const CSimulatorInfo & getSimulator() const
Simulator.
QStringList getInitializedModelDirectories(const QStringList &modelDirectories, const CSimulatorInfo &simulator) const
Get model directories from settings if empty, otherwise checked and UNC path fixed.
void loadingFinished(const CStatusMessageList &status, const CSimulatorInfo &simulator, IAircraftModelLoader::LoadFinishedInfo info)
Parsing is finished or cache has been loaded.
void diskLoadingStarted(const CSimulatorInfo &simulator, IAircraftModelLoader::LoadMode loadMode)
Disk loading started.
settings::CMultiSimulatorSettings m_settings
settings
CStatusMessageList m_loadingMessages
loading messages
@ LoadInBackground
load in background, asyncronously
@ LoadDirectly
load synchronously (blocking), normally for testing
CStatusMessage setCachedModels(const CAircraftModelList &models, const CSimulatorInfo &simulator)
Look like IMultiSimulatorModelCaches interface.
void setModelsForSimulator(const CAircraftModelList &models, const CSimulatorInfo &simulator)
Set models.
Set of aircraft.cfg entries representing an aircraft (FSX)
void setSimName(const QString &simName)
Simulator name.
void setDescription(const QString &description)
Description.
void setAtcAirline(const QString &airline)
Airline.
void setCreatedBy(const QString &createdBy)
Created by.
void setTitle(const QString &title)
Title.
void setAtcModel(const QString &atcModel)
ATC model.
void setTexture(const QString &texture)
Texture.
void setUiType(const QString &type)
UI type (e.g. A321-231 IAE)
void setRotorcraft(bool isRotorcraft)
Is Rotorcraft?
void setUiVariation(const QString &variation)
UI variation (e.g. White,Green)
void setAtcIdColor(const QString &color)
ATC color (e.g. 0xffffffff)
void setAtcType(const QString &atcType)
ATC type.
void setUiManufacturer(const QString &manufacturer)
UI manufacturer (e.g. Airbus)
void setAtcParkingCode(const QString &parkingCode)
Parking code.
Utility, providing FS aircraft.cfg entries.
swift::misc::simulation::CAircraftModelList toAircraftModelList(bool ignoreDuplicatesAndEmptyModelStrings, CStatusMessageList &msgs) const
As aircraft models.
Utility, parsing the aircraft.cfg files.
virtual bool isLoadingFinished() const
Loading finished?
CAircraftCfgParser(const CSimulatorInfo &simInfo, QObject *parent=nullptr)
Constructor.
static CAircraftCfgParser * createModelLoader(const CSimulatorInfo &simInfo, QObject *parent=nullptr)
Create an parser object for given simulator.
static CAircraftCfgEntriesList performParsingOfSingleFile(const QString &fileName, bool &ok, CStatusMessageList &msgs)
Parse a single file.
virtual ~CAircraftCfgParser()
Virtual destructor.
virtual void startLoadingFromDisk(LoadMode mode, const ModelConsolidationCallback &modelConsolidation, const QStringList &modelDirectories)
Start the loading process from disk.
static const QString & airFileFilter()
.air file filter
QStringList getModelExcludeDirectoryPatternsOrDefault(const CSimulatorInfo &simulator) const
Model exclude patterns per simulator.
Free functions in swift::misc.
SWIFT_MISC_EXPORT bool hasBalancedQuotes(const QString &in, char quote='"')
Has balanced quotes.
bool isValid() const const
bool open(FILE *fh, QIODeviceBase::OpenMode mode, QFileDevice::FileHandleFlags handleFlags)
virtual void close() override
QDateTime birthTime() const const
QDateTime lastModified() const const
void append(QList< T > &&value)
qsizetype size() const const
QObject * parent() const const
QVariant value(QAnyStringView key) const const
QString arg(Args &&... args) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString left(qsizetype n) &&
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) &&
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
qsizetype size() const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString toLower() const const
QString trimmed() const const
QString join(QChar separator) const const
QString readLine(qint64 maxlen)
bool isNull() const const
bool isValid() const const
QString toString() const const
QStringList toStringList() const const