13#include <QFileInfoList>
33using namespace swift::config;
35using namespace swift::misc::simulation;
36using namespace swift::misc::simulation::fscommon;
37using namespace swift::misc::network;
39namespace swift::misc::simulation::fscommon
42 using LoaderResponse = std::tuple<CAircraftCfgEntriesList, CAircraftModelList, CStatusMessageList>;
58 m_parserWorker->waitForFinished();
66 u
"Aircraft config parser loaded data");
68 u
"Aircraft config parser did NOT load data");
73 m_settings.getModelExcludeDirectoryPatternsOrDefault(simulator));
77 if (m_parserWorker && !m_parserWorker->isFinished())
84 [
this, modelDirs, excludedDirectoryPatterns, simulator, modelConsolidation]() {
87 this->performParsing(modelDirs, excludedDirectoryPatterns, msgs);
92 if (modelConsolidation)
94 modelConsolidation(models,
true);
97 return std::make_tuple(aircraftCfgEntriesList, models, msgs);
99 m_parserWorker->
thenWithResult<LoaderResponse>(
this, [
this, simulator](
const LoaderResponse &tuple) {
103 m_parsedCfgEntriesList = std::get<0>(tuple);
105 const bool hasData = !models.
isEmpty();
122 m_parsedCfgEntriesList = this->performParsing(modelDirs, excludedDirectoryPatterns, msgs);
123 const CAircraftModelList models(m_parsedCfgEntriesList.toAircraftModelList(simulator,
true, msgs));
126 const bool hasData = !models.
isEmpty();
143 for (
const QString &dir : directories)
145 entries.
push_back(this->performParsing(dir, excludeDirectories, messages));
172 static const QString NoNameFilter;
184 const QString currentDir = dir.absolutePath();
185 CAircraftCfgEntriesList result;
190 const QFileInfoList files =
198 const bool hasAirFiles = airFilesCount > 0;
202 const CStatusMessage m = CStatusMessage(
this).
warning(u
"No \"air\" files in '%1'") << currentDir;
206 for (
const auto &fileInfo : files)
212 if (fileInfo.isDir())
214 const QString nextDir = fileInfo.absoluteFilePath();
219 if (dir == currentDir)
224 const CAircraftCfgEntriesList subList(performParsing(nextDir, excludeDirectories, messages));
231 const CStatusMessage m = CStatusMessage(
this).
warning(u
"Parsing failed for '%1'") << nextDir;
247 const QString fileName = fileInfo.absoluteFilePath();
249 CStatusMessageList fileMsgs;
250 const CAircraftCfgEntriesList fileResults =
254 const CStatusMessage m = CStatusMessage(
this).
warning(u
"Parsing of '%1' failed") << fileName;
296 QString fltSection(
"[FLTSIM.0]");
297 static const QString fltSectionStr(
"[FLTSIM.%1]");
299 int fltsimCounter = 0;
300 FileSection currentSection = Unknown;
314 currentSection = General;
320 if (isRotorcraftPath)
325 currentSection = Fltsim;
326 fltSection = fltSectionStr.
arg(++fltsimCounter);
329 currentSection = Unknown;
332 switch (currentSection)
342 const QString c = getFixedIniLineContent(lineFixed);
388 bool r = getFixedIniLineContent(lineFixed).toLower().contains(
"rotor");
393 e.
setUiType(getFixedIniLineContent(lineFixed));
406 e.
setTexture(getFixedIniLineContent(lineFixed));
414 e.
setSimName(getFixedIniLineContent(lineFixed));
418 e.
setTitle(getFixedIniLineContent(lineFixed));
435 Q_ASSERT_X(fileTimestamp.
isValid(), Q_FUNC_INFO,
"Missing file timestamp");
440 if (e.getTitle().isEmpty())
443 .
info(u
"FS model in %1, index %2 has no title")
444 << fileName << e.getIndex();
460 return fixedStringContent(settings.value(key));
482 QString CAircraftCfgParser::getFixedIniLineContent(
const QString &line)
490 const int indexComment = line.
indexOf(
';');
491 QString content = QStringView { line }.left(indexComment - 1).trimmed().toString();
493 const int index = line.
indexOf(
'=');
498 if (line.
length() < index + 1)
503 content = QStringView { content }.
mid(index + 1).
trimmed().toString();
540 const QStringList &CAircraftCfgParser::fileNameFilters(
bool isMSFS,
bool isMSFS2024)
544 static const QStringList f({
"aircraft.cfg" });
549 static const QStringList f({
"aircraft.cfg",
"sim.cfg" });
554 bool CAircraftCfgParser::isExcludedSubDirectory(
const QString &checkDirectory)
561 if (dir == u
"texture" || dir.
startsWith(
"texture."))
565 if (dir == u
"sound" || dir ==
"soundai")
581Q_DECLARE_METATYPE(swift::misc::simulation::fscommon::LoaderResponse)
static int buildWordSize()
Whether this swift application is build as 32 or 64bit application.
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.
bool isEmpty() const
Synonym for empty.
Streamable status message, e.g.
static constexpr auto SeverityInfo
Status severities.
static constexpr auto SeverityError
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 thenWithResult(F functor)
Connects to a functor to which will be passed the result when the task is finished.
void setUtcTimestamp(const QDateTime ×tamp)
Set timestamp.
Value object encapsulating a list of aircraft models.
Simple hardcoded info about the corresponding 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
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.
const CSimulatorInfo & getSimulator() const
Simulator.
void diskLoadingStarted(const CSimulatorInfo &simulator, IAircraftModelLoader::LoadMode loadMode)
Disk loading started.
settings::CMultiSimulatorSettings m_settings
settings
IAircraftModelLoader(const CSimulatorInfo &simulator, QObject *parent=nullptr)
Constructor.
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.
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.
~CAircraftCfgParser()
Virtual destructor.
void startLoadingFromDisk(LoadMode mode, const ModelConsolidationCallback &modelConsolidation, const QStringList &modelDirectories)
Start the loading process from disk.
static const QString & airFileFilter()
.air file filter
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
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
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