mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-27 02:55:44 +08:00
Refactor shared X-Plane model parser in common header only functions
ref T290
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
#include "blackmisc/simulation/distributor.h"
|
#include "blackmisc/simulation/distributor.h"
|
||||||
#include "blackmisc/simulation/xplane/aircraftmodelloaderxplane.h"
|
#include "blackmisc/simulation/xplane/aircraftmodelloaderxplane.h"
|
||||||
#include "blackmisc/simulation/xplane/xplaneutil.h"
|
#include "blackmisc/simulation/xplane/xplaneutil.h"
|
||||||
|
#include "blackmisc/simulation/xplane/qtfreeutils.h"
|
||||||
#include "blackmisc/statusmessage.h"
|
#include "blackmisc/statusmessage.h"
|
||||||
#include "blackmisc/stringutils.h"
|
#include "blackmisc/stringutils.h"
|
||||||
#include "blackmisc/worker.h"
|
#include "blackmisc/worker.h"
|
||||||
@@ -62,30 +63,6 @@ namespace BlackMisc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Create a unique string to identify a model
|
|
||||||
static QString stringForFlyableModel(const CAircraftModel &model, const QFileInfo &acfFile)
|
|
||||||
{
|
|
||||||
if (model.getDistributor().hasDescription())
|
|
||||||
{
|
|
||||||
if (!model.getName().isEmpty())
|
|
||||||
{
|
|
||||||
if (model.getName().contains(model.getDistributor().getDescription()))
|
|
||||||
{
|
|
||||||
return model.getName();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return model.getDistributor().getDescription() % ' ' % model.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (model.hasAircraftDesignator())
|
|
||||||
{
|
|
||||||
return model.getDistributor().getDescription() % ' ' % model.getAircraftIcaoCodeDesignator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return acfFile.dir().dirName() % ' ' % acfFile.baseName();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Create a description string for a model that doesn't already have one
|
//! Create a description string for a model that doesn't already have one
|
||||||
static QString descriptionForFlyableModel(const CAircraftModel &model)
|
static QString descriptionForFlyableModel(const CAircraftModel &model)
|
||||||
{
|
{
|
||||||
@@ -217,7 +194,17 @@ namespace BlackMisc
|
|||||||
aircraftIt.next();
|
aircraftIt.next();
|
||||||
if (CFileUtils::isExcludedDirectory(aircraftIt.fileInfo(), excludeDirectories, Qt::CaseInsensitive)) { continue; }
|
if (CFileUtils::isExcludedDirectory(aircraftIt.fileInfo(), excludeDirectories, Qt::CaseInsensitive)) { continue; }
|
||||||
|
|
||||||
CAircraftModel model = this->extractAcfProperties(aircraftIt.filePath(), aircraftIt.fileInfo());
|
using namespace BlackMisc::Simulation::XPlane::QtFreeUtils;
|
||||||
|
AcfProperties acfProperties = extractAcfProperties(aircraftIt.filePath().toStdString());
|
||||||
|
|
||||||
|
const CDistributor dist({}, QString::fromStdString(acfProperties.author), {}, {}, CSimulatorInfo::XPLANE);
|
||||||
|
CAircraftModel model;
|
||||||
|
model.setAircraftIcaoCode(QString::fromStdString(acfProperties.aircraftIcaoCode));
|
||||||
|
model.setDescription(QString::fromStdString(acfProperties.modelDescription));
|
||||||
|
model.setName(QString::fromStdString(acfProperties.modelName));
|
||||||
|
model.setDistributor(dist);
|
||||||
|
model.setModelString(QString::fromStdString(acfProperties.modelString));
|
||||||
|
if (!model.hasDescription()) { model.setDescription(descriptionForFlyableModel(model)); }
|
||||||
model.setModelType(CAircraftModel::TypeOwnSimulatorModel);
|
model.setModelType(CAircraftModel::TypeOwnSimulatorModel);
|
||||||
model.setSimulator(CSimulatorInfo::xplane());
|
model.setSimulator(CSimulatorInfo::xplane());
|
||||||
model.setFileDetailsAndTimestamp(aircraftIt.fileInfo());
|
model.setFileDetailsAndTimestamp(aircraftIt.fileInfo());
|
||||||
@@ -236,59 +223,6 @@ namespace BlackMisc
|
|||||||
return installedModels;
|
return installedModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAircraftModel CAircraftModelLoaderXPlane::extractAcfProperties(const QString &filePath, const QFileInfo &fileInfo)
|
|
||||||
{
|
|
||||||
BlackMisc::Simulation::CAircraftModel model;
|
|
||||||
QFile file(filePath);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { return model; }
|
|
||||||
|
|
||||||
QTextStream ts(&file);
|
|
||||||
if (ts.readLine() == "I" && ts.readLine().contains("version") && ts.readLine() == "ACF")
|
|
||||||
{
|
|
||||||
while (!ts.atEnd())
|
|
||||||
{
|
|
||||||
const QString line = ts.readLine();
|
|
||||||
QVector<QStringRef> tokens = line.splitRef(' ', QString::SkipEmptyParts);
|
|
||||||
if (tokens.size() < 3 || tokens.at(0) != QLatin1String("P")) { continue; }
|
|
||||||
if (tokens.at(1) == QLatin1String("acf/_ICAO"))
|
|
||||||
{
|
|
||||||
const CAircraftIcaoCode icao(tokens.at(2).toString());
|
|
||||||
model.setAircraftIcaoCode(icao);
|
|
||||||
}
|
|
||||||
else if (tokens.at(1) == QLatin1String("acf/_descrip"))
|
|
||||||
{
|
|
||||||
const QString desc(line.mid(tokens.at(2).position()));
|
|
||||||
model.setDescription("[ACF] " % desc);
|
|
||||||
}
|
|
||||||
else if (tokens.at(1) == QLatin1String("acf/_name"))
|
|
||||||
{
|
|
||||||
const QString name(line.mid(tokens.at(2).position()));
|
|
||||||
model.setName(name);
|
|
||||||
}
|
|
||||||
else if (tokens.at(1) == QLatin1String("acf/_studio"))
|
|
||||||
{
|
|
||||||
const CDistributor dist({}, line.mid(tokens.at(2).position()), {}, {}, CSimulatorInfo::XPLANE);
|
|
||||||
model.setDistributor(dist);
|
|
||||||
}
|
|
||||||
else if (tokens.at(1) == QLatin1String("acf/_author"))
|
|
||||||
{
|
|
||||||
if (model.getDistributor().hasDescription()) { continue; }
|
|
||||||
thread_local const QRegularExpression end("\\W\\s", QRegularExpression::UseUnicodePropertiesOption);
|
|
||||||
QString author = line.mid(tokens.at(2).position());
|
|
||||||
author = author.left(author.indexOf(end)).trimmed();
|
|
||||||
if (author.isEmpty()) { continue; }
|
|
||||||
const CDistributor dist({}, author, {}, {}, CSimulatorInfo::XPLANE);
|
|
||||||
model.setDistributor(dist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
model.setModelString(stringForFlyableModel(model, fileInfo));
|
|
||||||
if (!model.hasDescription()) { model.setDescription(descriptionForFlyableModel(model)); }
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
CAircraftModelList CAircraftModelLoaderXPlane::parseCslPackages(const QString &rootDirectory, const QStringList &excludeDirectories)
|
CAircraftModelList CAircraftModelLoaderXPlane::parseCslPackages(const QString &rootDirectory, const QStringList &excludeDirectories)
|
||||||
{
|
{
|
||||||
Q_UNUSED(excludeDirectories);
|
Q_UNUSED(excludeDirectories);
|
||||||
|
|||||||
@@ -54,9 +54,6 @@ namespace BlackMisc
|
|||||||
//! Parsed or injected models
|
//! Parsed or injected models
|
||||||
void updateInstalledModels(const CAircraftModelList &models);
|
void updateInstalledModels(const CAircraftModelList &models);
|
||||||
|
|
||||||
//! Extract from an acf file (flyable plane) the properties needed to generate model string.
|
|
||||||
static CAircraftModel extractAcfProperties(const QString &filePath, const QFileInfo &fileInfo);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! \name Interface functions
|
//! \name Interface functions
|
||||||
//! @{
|
//! @{
|
||||||
|
|||||||
182
src/blackmisc/simulation/xplane/qtfreeutils.h
Normal file
182
src/blackmisc/simulation/xplane/qtfreeutils.h
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
/* Copyright (C) 2018
|
||||||
|
* 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 and at http://www.swift-project.org/license.html. 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_XPLANE_XPLANQTFREEUTILS_H
|
||||||
|
#define BLACKMISC_SIMULATION_XPLANE_XPLANQTFREEUTILS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Strict header only X-Plane model parser utils shared between BlackMisc and XSwiftBus.
|
||||||
|
// Header only is necessary to no require XSwiftBus to link against BlackMisc.
|
||||||
|
|
||||||
|
namespace BlackMisc
|
||||||
|
{
|
||||||
|
namespace Simulation
|
||||||
|
{
|
||||||
|
namespace XPlane
|
||||||
|
{
|
||||||
|
namespace QtFreeUtils
|
||||||
|
{
|
||||||
|
//! Get filename (including all extensions) from a filePath
|
||||||
|
std::string getFileName(const std::string &filePath)
|
||||||
|
{
|
||||||
|
const std::string seperator = "/\\";
|
||||||
|
const std::size_t sepPos = filePath.find_last_of(seperator);
|
||||||
|
if (sepPos != std::string::npos)
|
||||||
|
{
|
||||||
|
return filePath.substr(sepPos + 1, filePath.size() - 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Get the name of the parent directory
|
||||||
|
std::string getDirName(const std::string &filePath)
|
||||||
|
{
|
||||||
|
const std::string seperator = "/\\";
|
||||||
|
const std::size_t sepPos = filePath.find_last_of(seperator);
|
||||||
|
if (sepPos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string dirPath = filePath.substr(0, sepPos);
|
||||||
|
return getFileName(dirPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Get the base name of the file
|
||||||
|
std::string getBaseName(const std::string &filePath)
|
||||||
|
{
|
||||||
|
const std::string seperator = ".";
|
||||||
|
const std::string fileName = getFileName(filePath);
|
||||||
|
std::size_t sepPos = fileName.find(seperator);
|
||||||
|
if (sepPos != std::string::npos)
|
||||||
|
{
|
||||||
|
return fileName.substr(0, sepPos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Split string by delimiter and maxSplitCount times
|
||||||
|
std::vector<std::string> split(const std::string &str, size_t maxSplitCount = 0, const std::string &delimiter = " ")
|
||||||
|
{
|
||||||
|
std::string s(str);
|
||||||
|
size_t pos = 0;
|
||||||
|
std::vector<std::string> tokens;
|
||||||
|
while ((pos = s.find(delimiter)) != std::string::npos)
|
||||||
|
{
|
||||||
|
tokens.push_back(s.substr(0, pos));
|
||||||
|
s.erase(0, pos + delimiter.length());
|
||||||
|
if (maxSplitCount > 0 && tokens.size() == maxSplitCount) { break; }
|
||||||
|
}
|
||||||
|
tokens.push_back(s);
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
//! ACF properties
|
||||||
|
struct AcfProperties
|
||||||
|
{
|
||||||
|
std::string aircraftIcaoCode; //!< Aircraft ICAO code
|
||||||
|
std::string modelDescription; //!< Model description
|
||||||
|
std::string modelName; //!< Model name
|
||||||
|
std::string author; //!< Model author
|
||||||
|
std::string modelString; //!< Generated model string
|
||||||
|
};
|
||||||
|
|
||||||
|
//! Get the model string for a flyable aircraft
|
||||||
|
std::string stringForFlyableModel(const AcfProperties &acfProperties, const std::string &acfFile)
|
||||||
|
{
|
||||||
|
if (! acfProperties.author.empty())
|
||||||
|
{
|
||||||
|
if (! acfProperties.modelName.empty())
|
||||||
|
{
|
||||||
|
if (acfProperties.modelName.find(acfProperties.author) != std::string::npos) { return acfProperties.modelName; }
|
||||||
|
else { return acfProperties.author + ' ' + acfProperties.modelName; }
|
||||||
|
}
|
||||||
|
else if (! acfProperties.aircraftIcaoCode.empty())
|
||||||
|
{
|
||||||
|
return acfProperties.author + ' ' + acfProperties.aircraftIcaoCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getDirName(acfFile) + ' ' + getBaseName(acfFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Extract ACF properties from an aircraft file
|
||||||
|
AcfProperties extractAcfProperties(const std::string &filePath)
|
||||||
|
{
|
||||||
|
std::ifstream fs(filePath, std::ios::in);
|
||||||
|
if (!fs.is_open()) { return {}; }
|
||||||
|
|
||||||
|
std::string i;
|
||||||
|
std::string version;
|
||||||
|
std::string acf;
|
||||||
|
std::getline(fs, i);
|
||||||
|
std::getline(fs, version);
|
||||||
|
std::getline(fs, acf);
|
||||||
|
|
||||||
|
AcfProperties acfProperties;
|
||||||
|
|
||||||
|
if (i == "I" && version.find("version") != std::string::npos && acf == "ACF")
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(fs, line))
|
||||||
|
{
|
||||||
|
auto tokens = split(line, 2);
|
||||||
|
if (tokens.size() < 3 || tokens.at(0) != "P") { continue; }
|
||||||
|
|
||||||
|
if (tokens.at(1) == "acf/_ICAO")
|
||||||
|
{
|
||||||
|
acfProperties.aircraftIcaoCode = tokens.at(2);
|
||||||
|
}
|
||||||
|
else if (tokens.at(1) == "acf/_descrip")
|
||||||
|
{
|
||||||
|
acfProperties.modelDescription = "[ACF] " + tokens.at(2);
|
||||||
|
}
|
||||||
|
else if (tokens.at(1) == "acf/_name")
|
||||||
|
{
|
||||||
|
acfProperties.modelName = tokens.at(2);
|
||||||
|
}
|
||||||
|
else if (tokens.at(1) == "acf/_studio")
|
||||||
|
{
|
||||||
|
acfProperties.author = tokens.at(2);
|
||||||
|
}
|
||||||
|
else if (tokens.at(1) == "acf/_author")
|
||||||
|
{
|
||||||
|
if (!acfProperties.author.empty()) { continue; }
|
||||||
|
std::string author = tokens.at(2);
|
||||||
|
size_t pos = author.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_");
|
||||||
|
author = author.substr(0, pos);
|
||||||
|
if (author.empty()) { continue; }
|
||||||
|
acfProperties.author = author;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.close();
|
||||||
|
acfProperties.modelString = stringForFlyableModel(acfProperties, filePath);
|
||||||
|
return acfProperties;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
} // namespace
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
#endif // guard
|
||||||
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
/* Copyright (C) 2018
|
|
||||||
* 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 and at http://www.swift-project.org/license.html. 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 BLACKSIM_XSWIFTBUS_AIRCRAFTMODEL_H
|
|
||||||
#define BLACKSIM_XSWIFTBUS_AIRCRAFTMODEL_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace XSwiftBus
|
|
||||||
{
|
|
||||||
|
|
||||||
//! Simplified implementation of \sa BlackMisc::Simulation::CDistributor
|
|
||||||
class CDistributor
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
//! Default constructor
|
|
||||||
CDistributor() = default;
|
|
||||||
|
|
||||||
//! Constructor
|
|
||||||
CDistributor(const std::string &description) : m_description(description) {}
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CDistributor::hasDescription
|
|
||||||
bool hasDescription() const { return !m_description.empty(); }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CDistributor::getDescription
|
|
||||||
std::string getDescription() const { return m_description; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_description;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Simplified implementation of \sa BlackMisc::Simulation::CAircraftModel
|
|
||||||
class CAircraftModel
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CAircraftModel() = default;
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::hasDescription
|
|
||||||
bool hasDescription() const { return !m_description.empty(); }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::hasAircraftDesignator
|
|
||||||
bool hasAircraftDesignator() const { return !m_icao.empty(); }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::getName
|
|
||||||
std::string getName() const { return m_name; }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::getDistributor
|
|
||||||
CDistributor getDistributor() const { return m_distributor; }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::getAircraftIcaoCodeDesignator
|
|
||||||
std::string getAircraftIcaoCodeDesignator() const { return m_icao; }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::getModelString
|
|
||||||
std::string getModelString() const { return m_modelString; }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::setAircraftIcaoCode
|
|
||||||
void setAircraftIcaoCode(const std::string &icao) { m_icao = icao; }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::setDescription
|
|
||||||
void setDescription(const std::string &description) { m_description = description; }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::setName
|
|
||||||
void setName(const std::string &name) { m_name = name; }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::setDistributor
|
|
||||||
void setDistributor(const CDistributor &distributor) { m_distributor = distributor; }
|
|
||||||
|
|
||||||
//! \copydoc BlackMisc::Simulation::CAircraftModel::setModelString
|
|
||||||
void setModelString(const std::string &modelString) { m_modelString = modelString; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string m_name;
|
|
||||||
std::string m_icao;
|
|
||||||
std::string m_description;
|
|
||||||
CDistributor m_distributor;
|
|
||||||
std::string m_modelString;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // guard
|
|
||||||
@@ -8,13 +8,15 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "service.h"
|
#include "service.h"
|
||||||
|
#include "utils.h"
|
||||||
#include <XPLM/XPLMPlanes.h>
|
#include <XPLM/XPLMPlanes.h>
|
||||||
#include <XPLM/XPLMUtilities.h>
|
#include <XPLM/XPLMUtilities.h>
|
||||||
#include <fstream>
|
#include "blackmisc/simulation/xplane/qtfreeutils.h"
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
// clazy:excludeall=reserve-candidates
|
// clazy:excludeall=reserve-candidates
|
||||||
|
|
||||||
|
using namespace BlackMisc::Simulation::XPlane::QtFreeUtils;
|
||||||
|
|
||||||
namespace XSwiftBus
|
namespace XSwiftBus
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -29,8 +31,8 @@ namespace XSwiftBus
|
|||||||
char filename[256];
|
char filename[256];
|
||||||
char path[512];
|
char path[512];
|
||||||
XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
|
XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
|
||||||
const auto model = extractAcfProperties(path);
|
AcfProperties acfProperties = extractAcfProperties(path);
|
||||||
emitAircraftModelChanged(path, filename, getAircraftLivery(), getAircraftIcaoCode(), model.getModelString(), model.getName(), getAircraftDescription());
|
emitAircraftModelChanged(path, filename, getAircraftLivery(), getAircraftIcaoCode(), acfProperties.modelString, acfProperties.modelName, getAircraftDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CService::addTextMessage(const std::string &text, double red, double green, double blue)
|
void CService::addTextMessage(const std::string &text, double red, double green, double blue)
|
||||||
@@ -81,8 +83,8 @@ namespace XSwiftBus
|
|||||||
char filename[256];
|
char filename[256];
|
||||||
char path[512];
|
char path[512];
|
||||||
XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
|
XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
|
||||||
const auto model = extractAcfProperties(path);
|
const AcfProperties acfProperties = extractAcfProperties(path);
|
||||||
return model.getModelString();
|
return acfProperties.modelString;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CService::getAircraftName() const
|
std::string CService::getAircraftName() const
|
||||||
@@ -90,8 +92,8 @@ namespace XSwiftBus
|
|||||||
char filename[256];
|
char filename[256];
|
||||||
char path[512];
|
char path[512];
|
||||||
XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
|
XPLMGetNthAircraftModel(XPLM_USER_AIRCRAFT, filename, path);
|
||||||
const auto model = extractAcfProperties(path);
|
const AcfProperties acfProperties = extractAcfProperties(path);
|
||||||
return model.getName();
|
return acfProperties.modelName;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CService::getXPlaneVersionMajor() const
|
int CService::getXPlaneVersionMajor() const
|
||||||
@@ -672,117 +674,4 @@ namespace XSwiftBus
|
|||||||
return closestAirports;
|
return closestAirports;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Qt free version of BlackMisc::Simulation::XPlane::descriptionForFlyableModel()
|
|
||||||
std::string descriptionForFlyableModel(const CAircraftModel &model)
|
|
||||||
{
|
|
||||||
if (!model.getName().empty())
|
|
||||||
{
|
|
||||||
if (model.getDistributor().hasDescription() && model.getName().find(model.getDistributor().getDescription()) == std::string::npos)
|
|
||||||
{
|
|
||||||
return std::string("[ACF] ") + model.getName() + " by " + model.getDistributor().getDescription();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return std::string("[ACF] ") + model.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (model.hasAircraftDesignator())
|
|
||||||
{
|
|
||||||
if (model.getDistributor().hasDescription())
|
|
||||||
{
|
|
||||||
return std::string("[ACF] ") + model.getAircraftIcaoCodeDesignator() + " by " + model.getDistributor().getDescription();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return std::string("[ACF] ") + model.getAircraftIcaoCodeDesignator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return std::string("[ACF]");
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Qt free version of BlackMisc::Simulation::XPlane::stringForFlyableModel()
|
|
||||||
std::string stringForFlyableModel(const CAircraftModel &model, const std::string &acfFile)
|
|
||||||
{
|
|
||||||
if (model.getDistributor().hasDescription())
|
|
||||||
{
|
|
||||||
if (!model.getName().empty())
|
|
||||||
{
|
|
||||||
if (model.getName().find(model.getDistributor().getDescription()) != std::string::npos)
|
|
||||||
{
|
|
||||||
return model.getName();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return model.getDistributor().getDescription() + ' ' + model.getName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (model.hasAircraftDesignator())
|
|
||||||
{
|
|
||||||
return model.getDistributor().getDescription() + ' ' + model.getAircraftIcaoCodeDesignator();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getDirName(acfFile) + ' ' + getBaseName(acfFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
CAircraftModel CService::extractAcfProperties(const std::string &filePath)
|
|
||||||
{
|
|
||||||
CAircraftModel model;
|
|
||||||
|
|
||||||
std::ifstream fs(filePath, std::ios::in | std::ios::binary);
|
|
||||||
if (!fs.is_open()) { return model; }
|
|
||||||
|
|
||||||
std::string i;
|
|
||||||
std::string version;
|
|
||||||
std::string acf;
|
|
||||||
std::getline(fs, i);
|
|
||||||
std::getline(fs, version);
|
|
||||||
std::getline(fs, acf);
|
|
||||||
|
|
||||||
if (i == "I" && version.find("version") != std::string::npos && acf == "ACF")
|
|
||||||
{
|
|
||||||
std::string line;
|
|
||||||
while (std::getline(fs, line))
|
|
||||||
{
|
|
||||||
auto tokens = split(line, 2);
|
|
||||||
if (tokens.size() < 3 || tokens.at(0) != "P") { continue; }
|
|
||||||
if (tokens.at(1) == "acf/_ICAO")
|
|
||||||
{
|
|
||||||
const std::string icao(tokens.at(2));
|
|
||||||
model.setAircraftIcaoCode(icao);
|
|
||||||
}
|
|
||||||
else if (tokens.at(1) == "acf/_descrip")
|
|
||||||
{
|
|
||||||
const std::string desc(tokens.at(2));
|
|
||||||
model.setDescription("[ACF] " + desc);
|
|
||||||
}
|
|
||||||
else if (tokens.at(1) == "acf/_name")
|
|
||||||
{
|
|
||||||
const std::string name(tokens.at(2));
|
|
||||||
model.setName(name);
|
|
||||||
}
|
|
||||||
else if (tokens.at(1) == "acf/_studio")
|
|
||||||
{
|
|
||||||
const CDistributor dist(tokens.at(2));
|
|
||||||
model.setDistributor(dist);
|
|
||||||
}
|
|
||||||
else if (tokens.at(1) == "acf/_author")
|
|
||||||
{
|
|
||||||
if (model.getDistributor().hasDescription()) { continue; }
|
|
||||||
std::string author = tokens.at(2);
|
|
||||||
size_t pos = author.find_first_not_of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_");
|
|
||||||
author = author.substr(0, pos);
|
|
||||||
if (author.empty()) { continue; }
|
|
||||||
const CDistributor dist(author);
|
|
||||||
model.setDistributor(dist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.close();
|
|
||||||
|
|
||||||
model.setModelString(stringForFlyableModel(model, filePath));
|
|
||||||
if (!model.hasDescription()) { model.setDescription(descriptionForFlyableModel(model)); }
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
#include "datarefs.h"
|
#include "datarefs.h"
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
#include "navdatareference.h"
|
#include "navdatareference.h"
|
||||||
#include "aircraftmodel.h"
|
|
||||||
#include <XPLM/XPLMNavigation.h>
|
#include <XPLM/XPLMNavigation.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@@ -246,8 +245,6 @@ namespace XSwiftBus
|
|||||||
|
|
||||||
std::vector<CNavDataReference> findClosestAirports(int number, double latitude, double longitude);
|
std::vector<CNavDataReference> findClosestAirports(int number, double latitude, double longitude);
|
||||||
|
|
||||||
static CAircraftModel extractAcfProperties(const std::string &filePath);
|
|
||||||
|
|
||||||
StringDataRef<xplane::data::sim::aircraft::view::acf_livery_path> m_liveryPath;
|
StringDataRef<xplane::data::sim::aircraft::view::acf_livery_path> m_liveryPath;
|
||||||
StringDataRef<xplane::data::sim::aircraft::view::acf_ICAO> m_icao;
|
StringDataRef<xplane::data::sim::aircraft::view::acf_ICAO> m_icao;
|
||||||
StringDataRef<xplane::data::sim::aircraft::view::acf_descrip> m_descrip;
|
StringDataRef<xplane::data::sim::aircraft::view::acf_descrip> m_descrip;
|
||||||
|
|||||||
@@ -43,66 +43,6 @@ namespace XSwiftBus
|
|||||||
g_xplanePath = xplanePath;
|
g_xplanePath = xplanePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string getDirName(const std::string &filePath)
|
|
||||||
{
|
|
||||||
std::string seperator = "/\\";
|
|
||||||
std::size_t sepPos = filePath.find_last_of(seperator);
|
|
||||||
if (sepPos != std::string::npos)
|
|
||||||
{
|
|
||||||
std::string dirPath = filePath.substr(0, sepPos);
|
|
||||||
return getFileName(dirPath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getFileName(const std::string &filePath)
|
|
||||||
{
|
|
||||||
std::string seperator = "/\\";
|
|
||||||
std::size_t sepPos = filePath.find_last_of(seperator);
|
|
||||||
if (sepPos != std::string::npos)
|
|
||||||
{
|
|
||||||
return filePath.substr(sepPos + 1, filePath.size() - 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return filePath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getBaseName(const std::string &filePath)
|
|
||||||
{
|
|
||||||
std::string seperator = ".";
|
|
||||||
std::string fileName = getFileName(filePath);
|
|
||||||
std::size_t sepPos = fileName.find(seperator);
|
|
||||||
if (sepPos != std::string::npos)
|
|
||||||
{
|
|
||||||
return fileName.substr(0, sepPos);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return fileName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> split(const std::string &str, size_t maxSplitCount)
|
|
||||||
{
|
|
||||||
std::string s(str);
|
|
||||||
std::string delimiter = " ";
|
|
||||||
size_t pos = 0;
|
|
||||||
std::vector<std::string> tokens;
|
|
||||||
while ((pos = s.find(delimiter)) != std::string::npos)
|
|
||||||
{
|
|
||||||
tokens.push_back(s.substr(0, pos));
|
|
||||||
s.erase(0, pos + delimiter.length());
|
|
||||||
if (tokens.size() == maxSplitCount) { break; }
|
|
||||||
}
|
|
||||||
tokens.push_back(s);
|
|
||||||
return tokens;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Logger::print(const std::string &filePath, int line, MsgType type, const std::string &message)
|
void Logger::print(const std::string &filePath, int line, MsgType type, const std::string &message)
|
||||||
{
|
{
|
||||||
(void) line;
|
(void) line;
|
||||||
|
|||||||
@@ -26,19 +26,6 @@ namespace XSwiftBus
|
|||||||
//! Init global xplane path
|
//! Init global xplane path
|
||||||
void initXPlanePath();
|
void initXPlanePath();
|
||||||
|
|
||||||
//! Returns the directory name of a given file path
|
|
||||||
std::string getDirName(const std::string &filePath);
|
|
||||||
|
|
||||||
//! Returns the filename (including extension) of a given file path
|
|
||||||
std::string getFileName(const std::string &filePath);
|
|
||||||
|
|
||||||
//! Returns the filename without extension of a given file path
|
|
||||||
std::string getBaseName(const std::string &filePath);
|
|
||||||
|
|
||||||
//! Splits the given string maximal maxSplitCount times and returns the tokens
|
|
||||||
//! The size of the returned vector is up to maxSplitCount + 1 or less
|
|
||||||
std::vector<std::string> split(const std::string &str, size_t maxSplitCount = 0);
|
|
||||||
|
|
||||||
//! Simple logger class.
|
//! Simple logger class.
|
||||||
//! Don't use it directly, but the _LOG macros instead
|
//! Don't use it directly, but the _LOG macros instead
|
||||||
class Logger
|
class Logger
|
||||||
|
|||||||
Reference in New Issue
Block a user