refs #358, extended FS specific class for cfg entries

* more details fetched
* conversion to aircraft model / aircraft mode list (FS specific to generic)
* detect functions to find possible trouble makers
This commit is contained in:
Klaus Basan
2014-12-15 00:32:20 +01:00
parent bdcb031591
commit 3cdc485e56
4 changed files with 216 additions and 51 deletions

View File

@@ -12,6 +12,7 @@
#include "blackmisc/variant.h" #include "blackmisc/variant.h"
using namespace BlackMisc; using namespace BlackMisc;
using namespace BlackMisc::Network;
namespace BlackSim namespace BlackSim
{ {
@@ -21,9 +22,9 @@ namespace BlackSim
/* /*
* Constructor * Constructor
*/ */
CAircraftCfgEntries::CAircraftCfgEntries(const QString &filePath, qint32 index, const QString &title, const QString &atcType, const QString &atcModel, const QString &atcParkingCode) : CAircraftCfgEntries::CAircraftCfgEntries(const QString &filePath, qint32 index, const QString &title, const QString &atcType, const QString &atcModel, const QString &atcParkingCode, const QString &description) :
m_index(index), m_filePath(filePath), m_title(title), m_atcType(atcType), m_index(index), m_fileName(filePath), m_title(title.trimmed()), m_atcType(atcType.trimmed()),
m_atcModel(atcModel), m_atcParkingCode(atcParkingCode) m_atcModel(atcModel.trimmed()), m_atcParkingCode(atcParkingCode.trimmed()), m_description(description.trimmed())
{ {
// void // void
} }
@@ -34,11 +35,35 @@ namespace BlackSim
QString CAircraftCfgEntries::convertToQString(bool) const QString CAircraftCfgEntries::convertToQString(bool) const
{ {
QString s = "{%1, %2, %3, %4, %5, %6}"; QString s = "{%1, %2, %3, %4, %5, %6}";
s = s.arg(this->m_filePath).arg(this->m_index).arg(this->m_title) s = s.arg(this->m_fileName).arg(this->m_index).arg(this->m_title)
.arg(this->m_atcModel).arg(this->m_atcType).arg(this->m_atcParkingCode); .arg(this->m_atcModel).arg(this->m_atcType).arg(this->m_atcParkingCode);
return s; return s;
} }
/*
* Aircraft model
*/
QString CAircraftCfgEntries::getUiCombinedDescription() const
{
QString d(this->m_uiManufacturer);
if (m_uiType.isEmpty()) { return d; }
if (d.isEmpty()) { return m_uiType; }
d += " ";
d += m_uiType;
return d;
}
/*
* Convert
*/
CAircraftModel CAircraftCfgEntries::toAircraftModel() const
{
CAircraftModel model(this->getTitle(), CAircraftModel::TypeModelMapping);
model.setDescription(this->getUiCombinedDescription());
model.setFileName(this->getFileName());
return model;
}
/* /*
* Get particular column * Get particular column
*/ */
@@ -48,8 +73,8 @@ namespace BlackSim
ColumnIndex i = index.frontCasted<ColumnIndex>(); ColumnIndex i = index.frontCasted<ColumnIndex>();
switch (i) switch (i)
{ {
case IndexFilePath: case IndexFileName:
return CVariant::from(this->m_filePath); return CVariant::from(this->m_fileName);
case IndexTitle: case IndexTitle:
return CVariant::from(this->m_title); return CVariant::from(this->m_title);
case IndexAtcType: case IndexAtcType:
@@ -83,8 +108,8 @@ namespace BlackSim
case IndexEntryIndex: case IndexEntryIndex:
this->setIndex(variant.toInt()); this->setIndex(variant.toInt());
break; break;
case IndexFilePath: case IndexFileName:
this->setFilePath(variant.toQString()); this->setFileName(variant.toQString());
break; break;
case IndexParkingCode: case IndexParkingCode:
this->setAtcParkingCode(variant.toQString()); this->setAtcParkingCode(variant.toQString());

View File

@@ -13,6 +13,8 @@
#define BLACKSIM_FSCOMMON_AIRCRAFTCFGENTRY_H #define BLACKSIM_FSCOMMON_AIRCRAFTCFGENTRY_H
#include "blackmisc/propertyindex.h" #include "blackmisc/propertyindex.h"
#include "blackmisc/nwaircraftmodel.h"
#include "blackmisc/variant.h"
namespace BlackSim namespace BlackSim
{ {
@@ -30,29 +32,22 @@ namespace BlackSim
enum ColumnIndex enum ColumnIndex
{ {
IndexEntryIndex = BlackMisc::CPropertyIndex::GlobalIndexCAircraftCfgEntries, IndexEntryIndex = BlackMisc::CPropertyIndex::GlobalIndexCAircraftCfgEntries,
IndexFilePath, IndexFileName,
IndexTitle, IndexTitle,
IndexAtcType, IndexAtcType,
IndexAtcModel, IndexAtcModel,
IndexParkingCode IndexParkingCode,
IndexDescription
}; };
//! Default constructor //! Default constructor
CAircraftCfgEntries() = default; CAircraftCfgEntries() = default;
/*! //! Entries representing an aircraft
* Entries representing an aircraft CAircraftCfgEntries(const QString &filePath, int index, const QString &title, const QString &atcType, const QString &atcModel, const QString &atcParkingCode, const QString &description);
* \param filePath
* \param index
* \param title
* \param atcType
* \param atcModel
* \param atcParkingCode
*/
CAircraftCfgEntries(const QString &filePath, int index, const QString &title, const QString &atcType, const QString &atcModel, const QString &atcParkingCode);
//! Filepath //! File name
QString getFilePath() const { return this->m_filePath; } QString getFileName() const { return this->m_fileName; }
//! Title //! Title
QString getTitle() const { return this->m_title; } QString getTitle() const { return this->m_title; }
@@ -66,11 +61,23 @@ namespace BlackSim
//! ATC type //! ATC type
QString getAtcType() const { return this->m_atcType; } QString getAtcType() const { return this->m_atcType; }
//! Description
QString getDescription() const { return this->m_description; }
//! ATC parking code //! ATC parking code
QString getAtcParkingCode() const { return this->m_atcParkingCode; } QString getAtcParkingCode() const { return this->m_atcParkingCode; }
//! UI type (e.g. A321-231 IAE)
QString getUiType() const { return this->m_uiType; }
//! UI manufacturer (e.g. Airbus)
QString getUiManufacturer() const { return this->m_uiManufacturer; }
//! Manufacturer + type
QString getUiCombinedDescription() const;
//! Filepath //! Filepath
void setFilePath(const QString &filePath) { this->m_filePath = filePath; } void setFileName(const QString &filePath) { this->m_fileName = filePath; }
//! Title //! Title
void setTitle(const QString &title) { this->m_title = title; } void setTitle(const QString &title) { this->m_title = title; }
@@ -79,13 +86,25 @@ namespace BlackSim
void setIndex(int index) { this->m_index = index; } void setIndex(int index) { this->m_index = index; }
//! ATC model //! ATC model
void setAtcModel(const QString &atcModel) { this->m_atcModel = atcModel; } void setAtcModel(const QString &atcModel) { this->m_atcModel = atcModel.trimmed(); }
//! ATC type //! ATC type
void setAtcType(const QString &atcType) { this->m_atcType = atcType; } void setAtcType(const QString &atcType) { this->m_atcType = atcType.trimmed(); }
//! Parking code //! Parking code
void setAtcParkingCode(const QString &parkingCode) { this->m_atcParkingCode = parkingCode; } void setAtcParkingCode(const QString &parkingCode) { this->m_atcParkingCode = parkingCode.trimmed(); }
//! Description
void setDescription(const QString &description) { this->m_description = description.trimmed(); }
//! UI type (e.g. A321-231 IAE)
void setUiType(const QString &type) { this->m_uiType = type.trimmed(); }
//! UI manufacturer (e.g. Airbus)
void setUiManufacturer(const QString &manufacturer) { this->m_uiManufacturer = manufacturer.trimmed(); }
//! To aircraft model
BlackMisc::Network::CAircraftModel toAircraftModel() const;
//! \copydoc CValueObject::propertyByIndex //! \copydoc CValueObject::propertyByIndex
virtual BlackMisc::CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const override; virtual BlackMisc::CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const override;
@@ -99,18 +118,20 @@ namespace BlackSim
private: private:
BLACK_ENABLE_TUPLE_CONVERSION(CAircraftCfgEntries) BLACK_ENABLE_TUPLE_CONVERSION(CAircraftCfgEntries)
int m_index; //!< current index in given config int m_index; //!< current index in given config
QString m_filePath; //!< file path of aircraft.cfg QString m_fileName; //!< file name of aircraft.cfg
QString m_title; //!< Title in aircraft.cfg QString m_title; //!< Title in aircraft.cfg
QString m_atcType; //!< ATC type QString m_atcType; //!< ATC type
QString m_atcModel; //!< ATC model QString m_atcModel; //!< ATC model
QString m_atcParkingCode; //!< ATC parking code QString m_atcParkingCode; //!< ATC parking code
QString m_description; //!< descriptive text
QString m_uiType; //!< e.g. A321-231 IAE
QString m_uiManufacturer; //!< e.g. Airbus
}; };
} }
} }
BLACK_DECLARE_TUPLE_CONVERSION(BlackSim::FsCommon::CAircraftCfgEntries, (o.m_index, o.m_filePath, o.m_title, o.m_atcType, o.m_atcModel, o.m_atcParkingCode)) BLACK_DECLARE_TUPLE_CONVERSION(BlackSim::FsCommon::CAircraftCfgEntries, (o.m_index, o.m_fileName, o.m_title, o.m_atcType, o.m_atcModel, o.m_atcParkingCode))
Q_DECLARE_METATYPE(BlackSim::FsCommon::CAircraftCfgEntries) Q_DECLARE_METATYPE(BlackSim::FsCommon::CAircraftCfgEntries)
#endif // guard #endif // guard

View File

@@ -8,6 +8,13 @@
*/ */
#include "aircraftcfgentrieslist.h" #include "aircraftcfgentrieslist.h"
#include "blackmisc/predicates.h"
#include "blackmisc/logmessage.h"
#include <QFuture>
#include <QtConcurrent/QtConcurrent>
using namespace BlackMisc;
using namespace BlackMisc::Network;
namespace BlackSim namespace BlackSim
{ {
@@ -20,9 +27,10 @@ namespace BlackSim
bool CAircraftCfgEntriesList::existsDir(const QString &directory) const bool CAircraftCfgEntriesList::existsDir(const QString &directory) const
{ {
QString d = directory.isEmpty() ? this->m_rootDirectory : directory; QString d = directory.isEmpty() ? this->m_rootDirectory : directory;
if (d.isEmpty()) return false; if (d.isEmpty()) { return false; }
QDir dir(d); QDir dir(d);
return (dir.exists()); //! \todo not available network dir can make this hang here
return dir.exists();
} }
/* /*
@@ -30,14 +38,62 @@ namespace BlackSim
*/ */
bool CAircraftCfgEntriesList::containsModelWithTitle(const QString &title, Qt::CaseSensitivity caseSensitivity) bool CAircraftCfgEntriesList::containsModelWithTitle(const QString &title, Qt::CaseSensitivity caseSensitivity)
{ {
return this->containsBy([ = ](const CAircraftCfgEntries & entries) -> bool if (title.isEmpty()) { return false; }
{ return title.compare(entries.getTitle(), caseSensitivity) == 0; }); return this->containsBy(
[ = ](const CAircraftCfgEntries & entries) -> bool { return title.compare(entries.getTitle(), caseSensitivity) == 0; }
);
}
/*
* Double titles
*/
QStringList CAircraftCfgEntriesList::detectAmbiguousTitles() const
{
QStringList titles = this->getTitles(true);
QStringList ambiguousTitles;
QString last;
foreach(QString title, titles)
{
if (title.isEmpty()) { continue; }
if (title.compare(last, Qt::CaseInsensitive) == 0)
{
if (!ambiguousTitles.contains(title, Qt::CaseInsensitive))
{
ambiguousTitles.append(title);
}
}
last = title;
}
return ambiguousTitles;
}
/*
* All titles
*/
QStringList CAircraftCfgEntriesList::getTitles(bool sorted) const
{
QStringList titles = this->transform(Predicates::MemberTransform(&CAircraftCfgEntries::getTitle));
if (sorted) { titles.sort(Qt::CaseInsensitive); }
return titles;
}
/*
* As model list
*/
CAircraftModelList CAircraftCfgEntriesList::toAircraftModelList() const
{
CAircraftModelList ml;
for (auto it = this->begin() ; it != this->end(); ++it)
{
ml.push_back(it->toAircraftModel());
}
return ml;
} }
/* /*
* Models for title * Models for title
*/ */
CAircraftCfgEntriesList CAircraftCfgEntriesList::findByTitle(const QString &title, Qt::CaseSensitivity caseSensitivity) CAircraftCfgEntriesList CAircraftCfgEntriesList::findByTitle(const QString &title, Qt::CaseSensitivity caseSensitivity) const
{ {
return this->findBy([ = ](const CAircraftCfgEntries & entries) -> bool return this->findBy([ = ](const CAircraftCfgEntries & entries) -> bool
{ return title.compare(entries.getTitle(), caseSensitivity) == 0; }); { return title.compare(entries.getTitle(), caseSensitivity) == 0; });
@@ -48,6 +104,8 @@ namespace BlackSim
*/ */
int CAircraftCfgEntriesList::read(const QString &directory) int CAircraftCfgEntriesList::read(const QString &directory)
{ {
if (m_cancelRead) { return -1; }
// set directory with name filters, get aircraft.cfg and sub directories // set directory with name filters, get aircraft.cfg and sub directories
QDir dir(directory, "aircraft.cfg", QDir::Name, QDir::Files | QDir::AllDirs); QDir dir(directory, "aircraft.cfg", QDir::Name, QDir::Files | QDir::AllDirs);
if (!dir.exists()) return 0; // can happen if there are shortcuts or linked dirs not available if (!dir.exists()) return 0; // can happen if there are shortcuts or linked dirs not available
@@ -60,6 +118,7 @@ namespace BlackSim
foreach(QFileInfo file, files) foreach(QFileInfo file, files)
{ {
if (m_cancelRead) { return -1; }
if (file.isDir()) if (file.isDir())
{ {
QString nextDir = file.absoluteFilePath(); QString nextDir = file.absoluteFilePath();
@@ -74,28 +133,44 @@ namespace BlackSim
// I abuse the QSettings as ini-file reader // I abuse the QSettings as ini-file reader
QSettings aircraftCfg(path, QSettings::IniFormat); QSettings aircraftCfg(path, QSettings::IniFormat);
// from the general section
const QString atcType = aircraftCfg.value("atc_type").toString(); const QString atcType = aircraftCfg.value("atc_type").toString();
const QString atcModel = aircraftCfg.value("atc_model").toString(); const QString atcModel = aircraftCfg.value("atc_model").toString();
int index = 0; int index = 0;
while (index >= 0) while (index >= 0)
{ {
if (m_cancelRead) { return -1; }
QString group = QString("fltsim.%1").arg(index); QString group = QString("fltsim.%1").arg(index);
aircraftCfg.beginGroup(group); aircraftCfg.beginGroup(group);
// does group exist?
if (aircraftCfg.contains("title")) if (aircraftCfg.contains("title"))
{ {
CAircraftCfgEntries entry(path, index, "", atcType, atcModel, ""); QString title = fixedStringContent(aircraftCfg, "title");
entry.setTitle(aircraftCfg.value("title").toString()); if (!title.isEmpty())
entry.setAtcParkingCode(aircraftCfg.value("atc_parking_codes").toString()); {
this->push_back(entry); CAircraftCfgEntries entry(path, index, title, atcType, atcModel, "", "");
aircraftCfg.endGroup(); entry.setAtcParkingCode(fixedStringContent(aircraftCfg, "atc_parking_codes"));
entry.setDescription(fixedStringContent(aircraftCfg, "description"));
entry.setUiManufacturer(fixedStringContent(aircraftCfg, "ui_manufacturer"));
entry.setUiType(fixedStringContent(aircraftCfg, "ui_type"));
this->push_back(entry);
}
else
{
CLogMessage(this).info("FSX model in %1, index %2 has no title") << path << index;
}
++index; ++index;
++counter; ++counter;
} }
else else
{ {
// marks end of the "fltsim.x" groups
index = -1; index = -1;
} }
aircraftCfg.endGroup();
} }
break; break;
} }
@@ -103,6 +178,30 @@ namespace BlackSim
return counter; return counter;
} }
QString CAircraftCfgEntriesList::fixedStringContent(const QSettings &settings, const QString &key)
{
return fixedStringContent(settings.value(key));
}
QString CAircraftCfgEntriesList::fixedStringContent(const QVariant &qv)
{
if (qv.isNull() || !qv.isValid())
{
return ""; // normal when there is no settings value
}
else if (qv.type() == QMetaType::QStringList)
{
QStringList l = qv.toStringList();
return l.join(",").trimmed();
}
else if (qv.type() == QMetaType::QString)
{
return qv.toString().trimmed();
}
Q_ASSERT(false);
return "";
}
/* /*
* Register metadata * Register metadata
*/ */

View File

@@ -9,12 +9,14 @@
//! \file //! \file
#ifndef BLACKSIM_FSCOMMON_AIRCRAFTCFG_H #ifndef BLACKSIM_FSCOMMON_AIRCRAFTCFGLIST_H
#define BLACKSIM_FSCOMMON_AIRCRAFTCFG_H #define BLACKSIM_FSCOMMON_AIRCRAFTCFGLIST_H
#include "aircraftcfgentries.h" #include "aircraftcfgentries.h"
#include "blackmisc/sequence.h" #include "blackmisc/sequence.h"
#include "blackmisc/collection.h" #include "blackmisc/collection.h"
#include "blackmisc/nwaircraftmodellist.h"
#include <QDir> #include <QDir>
#include <QVector> #include <QVector>
#include <QDebug> #include <QDebug>
@@ -32,12 +34,12 @@ namespace BlackSim
public: public:
//! Constructor //! Constructor
CAircraftCfgEntriesList(const QString &rootDirectory = "") : m_rootDirectory(rootDirectory), m_readForDirectory(false) {} CAircraftCfgEntriesList(const QString &rootDirectory = "") : m_rootDirectory(rootDirectory) {}
//! Read all aircraft.cfg files starting from root directory //! Read all aircraft.cfg files starting from root directory
int read() int read()
{ {
if (this->m_readForDirectory) return this->size(); if (this->m_readForDirectory) { return this->size(); }
// not read so far, read it // not read so far, read it
this->clear(); this->clear();
@@ -53,7 +55,7 @@ namespace BlackSim
this->m_rootDirectory = directory; this->m_rootDirectory = directory;
this->m_readForDirectory = false; this->m_readForDirectory = false;
} }
return !directory.isEmpty() && this->existsDir(directory); return (!directory.isEmpty() && this->existsDir(directory));
} }
//! Virtual destructor //! Virtual destructor
@@ -65,14 +67,26 @@ namespace BlackSim
//! Has current directory been read? //! Has current directory been read?
bool hasReadDirectory() const { return this->m_readForDirectory; } bool hasReadDirectory() const { return this->m_readForDirectory; }
//! Cancel read
void cancelRead() { m_cancelRead = true; }
//! Current root directory //! Current root directory
QString getRootDirectory() const { return this->m_rootDirectory; } QString getRootDirectory() const { return this->m_rootDirectory; }
//! Contains model with title? //! Contains model with title?
bool containsModelWithTitle(const QString &title, Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive); bool containsModelWithTitle(const QString &title, Qt::CaseSensitivity caseSensitivity = Qt::CaseInsensitive);
//! All titles (aka model names)
QStringList getTitles(bool sorted = false) const;
//! As aircraft models
BlackMisc::Network::CAircraftModelList toAircraftModelList() const;
//! Ambiguous titles
QStringList detectAmbiguousTitles() const;
//! Find by title //! Find by title
CAircraftCfgEntriesList findByTitle(const QString &title, Qt::CaseSensitivity caseSensitivity); CAircraftCfgEntriesList findByTitle(const QString &title, Qt::CaseSensitivity caseSensitivity) const;
//! \copydoc CValueObject::toQVariant //! \copydoc CValueObject::toQVariant
virtual QVariant toQVariant() const override { return QVariant::fromValue(*this); } virtual QVariant toQVariant() const override { return QVariant::fromValue(*this); }
@@ -91,12 +105,18 @@ namespace BlackSim
static void registerMetadata(); static void registerMetadata();
private: private:
QString m_rootDirectory; //!< root directory reading aircraft.cfg files QString m_rootDirectory; //!< root directory reading aircraft.cfg files
bool m_readForDirectory; //!< valid read for given directory bool m_readForDirectory = false; //!< valid read for given directory
bool m_cancelRead = false;
//! Read all entries in one directory //! Read all entries in one directory
int read(const QString &directory); int read(const QString &directory);
//! Fix the content read
static QString fixedStringContent(const QVariant &qv);
//! Value from settings, fixed string
static QString fixedStringContent(const QSettings &settings, const QString &key);
}; };
} // namespace } // namespace
} // namespace } // namespace