9 #include <QDomDocument>
10 #include <QDomNamedNodeMap>
12 #include <QDomNodeList>
15 #include <QFileInfoList>
17 #include <QReadLocker>
18 #include <QStandardPaths>
20 #include <QWriteLocker>
31 namespace swift::misc::simulation::fscommon
42 QReadLocker l(&m_lockData);
48 QReadLocker l(&m_lockData);
49 return !m_fileList.isEmpty();
54 QWriteLocker l(&m_lockData);
55 if (this->m_fileList.contains(fileName)) {
return; }
56 this->m_fileList.append(fileName);
62 if (!dir.exists()) {
return; }
63 QStringList nameFilters({
"*.vmr" });
64 QFileInfoList entries = dir.entryInfoList(nameFilters, QDir::Files | QDir::Readable);
65 for (
const QFileInfo &file : entries) { this->
addFilename(file.absoluteFilePath()); }
70 QReadLocker l(&m_lockData);
76 QReadLocker l(&m_lockData);
86 if (!vPilotModels.
isEmpty() || m_rules.
isEmpty()) {
return vPilotModels; }
92 this->ps_setCache(vPilotModels);
100 QReadLocker l(&m_lockData);
101 return m_rules.
size();
106 QWriteLocker l(&m_lockData);
113 static QString directory;
114 if (directory.isEmpty())
116 directory = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation).constFirst();
117 if (!directory.endsWith(
'/')) { directory.append(
'/'); }
118 directory.append(
"vPilot Files/Model Matching Rule Sets");
126 QStringList filesWithProblems;
128 const QStringList fileList(
getFiles());
129 for (
const QString &fn : fileList)
131 if (m_shutdown) {
return false; }
133 bool s = this->loadFile(fn, rules);
134 if (!s) { filesWithProblems.append(fn); }
138 QWriteLocker l(&m_lockData);
139 this->m_loadedFiles = loadedFiles;
140 this->m_fileListWithProblems = filesWithProblems;
141 this->m_rules = rules;
142 if (m_shutdown) {
return false; }
145 const bool success = loadedFiles > 0;
149 this->ps_setCache(vPilotModels);
160 QWriteLocker l(&m_lockData);
161 if (m_asyncLoadInProgress || m_shutdown) {
return nullptr; }
162 m_asyncLoadInProgress =
true;
165 this,
"CVPilotRulesReader", [
this, convertToModels]() { this->
read(convertToModels); });
166 worker->
then(
this, &CVPilotRulesReader::ps_readInBackgroundFinished);
170 void CVPilotRulesReader::ps_readInBackgroundFinished()
172 QWriteLocker l(&m_lockData);
173 m_asyncLoadInProgress =
false;
176 void CVPilotRulesReader::ps_onVPilotCacheChanged()
181 void CVPilotRulesReader::ps_setCache(
const CAircraftModelList &models)
183 if (this->m_cachedVPilotModels.isOwnerThread())
187 QWriteLocker l(&m_lockData);
188 m = this->m_cachedVPilotModels.set(models);
198 bool CVPilotRulesReader::loadFile(
const QString &fileName, CVPilotModelRuleSet &ruleSet)
201 if (!f.exists()) {
return false; }
202 if (!f.open(QFile::ReadOnly | QFile::Text)) {
return false; }
203 QByteArray fc = f.readAll();
204 if (fc.isEmpty()) {
return false; }
206 if (!doc.setContent(fc)) {
return false; }
207 QDomNodeList rules = doc.elementsByTagName(
"ModelMatchRule");
208 if (rules.isEmpty()) {
return false; }
210 QDomNodeList mmRuleSet = doc.elementsByTagName(
"ModelMatchRuleSet");
211 if (mmRuleSet.size() < 1) {
return true; }
213 const QDomNamedNodeMap attributes = mmRuleSet.at(0).attributes();
214 QString folder = attributes.namedItem(
"Folder").nodeValue().trimmed();
215 if (folder.isEmpty()) { folder = QFileInfo(fileName).fileName().replace(
".vmr",
""); }
218 const QString updated = attributes.namedItem(
"UpdatedOn").nodeValue();
219 QDateTime qt =
fromStringUtc(updated,
"M/d/yyyy h:mm:ss AP");
220 qint64 updatedTimestamp = qt.toMSecsSinceEpoch();
222 int rulesSize = rules.size();
223 for (
int i = 0; i < rulesSize; i++)
225 const QDomNamedNodeMap ruleAttributes = rules.at(i).attributes();
226 const QString typeCode = ruleAttributes.namedItem(
"TypeCode").nodeValue();
227 const QString modelName = ruleAttributes.namedItem(
"ModelName").nodeValue();
229 const QString callsignPrefix = ruleAttributes.namedItem(
"CallsignPrefix").nodeValue();
230 if (modelName.isEmpty()) {
continue; }
233 if (modelName.contains(
"//"))
236 const QStringList models = modelName.split(
"//");
237 for (
const QString &model : models)
239 if (model.isEmpty()) {
continue; }
240 CVPilotModelRule rule(model, folder, typeCode, callsignPrefix, updatedTimestamp);
241 ruleSet.push_back(rule);
247 CVPilotModelRule rule(modelName, folder, typeCode, callsignPrefix, updatedTimestamp);
248 ruleSet.push_back(rule);
size_type size() const
Returns number of elements in the collection.
bool isEmpty() const
Synonym for empty.
static void preformatted(const CStatusMessage &statusMessage)
Sends a verbatim, preformatted message to the log.
bool isEmpty() const
Synonym for empty.
Streamable status message, e.g.
bool isFailure() const
Operation considered unsuccessful.
void then(T *context, F functor)
Connects to a functor or method which will be called when the task is finished.
Class for doing some arbitrary parcel of work in its own thread.
static CWorker * fromTask(QObject *owner, const QString &name, F &&task)
Returns a new worker object which lives in a new thread.
Value object encapsulating a list of aircraft models.
Value object reading a set of vPilot rules.
simulation::CAircraftModelList toAircraftModels() const
To aircraft models.
swift::misc::simulation::CAircraftModelList getAsModels()
Get as models.
void gracefulShutdown()
Graceful shutdown.
int getModelsCount() const
Get model count.
CVPilotRulesReader(bool standardDirectory=true, QObject *parent=nullptr)
Constructor.
void addFilename(const QString &fileName)
File names.
swift::misc::simulation::CAircraftModelList getAsModelsFromCache() const
Get as models from cache.
int countRulesLoaded() const
Loaded rules.
static const QString & standardMappingsDirectory()
The standard directory for vPilot mappings.
int countFilesLoaded() const
Loaded files (number)
bool hasFiles() const
Has files.
QStringList getFiles() const
Files.
void addDirectory(const QString &directory)
Directory with .vmr files.
void readFinished(bool success)
Rules read.
bool read(bool convertToModels)
Load data.
swift::misc::CWorker * readInBackground(bool convertToModels)
Load data in background thread.
~CVPilotRulesReader()
Destructor.
CVPilotModelRuleSet getRules() const
Loaded rules.
Free functions in swift::misc.
SWIFT_MISC_EXPORT QDateTime fromStringUtc(const QString &dateTimeString, const QString &format)
Same as QDateTime::fromString but QDateTime will be set to UTC.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...