refs #619, change model loader to use caches (one per simulator)

* removed caching from GUI component
* added caches in model loader
* adjusted samples
This commit is contained in:
Klaus Basan
2016-03-11 04:13:56 +01:00
parent eda68329f3
commit 4087d63d9c
13 changed files with 354 additions and 151 deletions

View File

@@ -15,6 +15,8 @@
#include "blackmisc/simulation/fscommon/aircraftcfgentrieslist.h" #include "blackmisc/simulation/fscommon/aircraftcfgentrieslist.h"
#include "blackmisc/simulation/fscommon/aircraftcfgparser.h" #include "blackmisc/simulation/fscommon/aircraftcfgparser.h"
#include "blackmisc/simulation/aircraftmatcher.h" #include "blackmisc/simulation/aircraftmatcher.h"
#include "blackmisc/simulation/simulatorinfo.h"
#include <QDebug> #include <QDebug>
#include <QFuture> #include <QFuture>
@@ -24,16 +26,17 @@
#include <QJsonDocument> #include <QJsonDocument>
using namespace BlackMisc; using namespace BlackMisc;
using namespace BlackMisc::Simulation;
using namespace BlackMisc::Simulation::FsCommon; using namespace BlackMisc::Simulation::FsCommon;
namespace BlackSample namespace BlackSample
{ {
void CSamplesFsCommon::samples(QTextStream &streamOut, QTextStream &streamIn) void CSamplesFsCommon::samples(QTextStream &streamOut, QTextStream &streamIn)
{ {
QString fsxDir = CSampleUtils::selectDirectory({"C:/Program Files (x86)/Microsoft Games/Microsoft Flight Simulator X/SimObjects", const QString fsxDir = CSampleUtils::selectDirectory({"C:/Program Files (x86)/Microsoft Games/Microsoft Flight Simulator X/SimObjects",
"C:/Flight Simulator 9/Aircraft"}, streamOut, streamIn); "C:/Flight Simulator 9/Aircraft"}, streamOut, streamIn);
CAircraftCfgParser parser; CAircraftCfgParser parser(CSimulatorInfo(CSimulatorInfo::FSX), fsxDir);
parser.changeRootDirectory(fsxDir); parser.changeRootDirectory(fsxDir);
streamOut << "start reading, press RETURN" << endl; streamOut << "start reading, press RETURN" << endl;

View File

@@ -43,12 +43,12 @@ namespace BlackSample
streamOut << "loaded: " << BlackMisc::boolToYesNo(s) << " size: " << cvm->getDatastoreModels().size() << endl; streamOut << "loaded: " << BlackMisc::boolToYesNo(s) << " size: " << cvm->getDatastoreModels().size() << endl;
// mapper with rule set, handing over ownership // mapper with rule set, handing over ownership
CAircraftCfgParser cfgParser;
QString fsxDir = CSampleUtils::selectDirectory({QStringLiteral("P:/FlightSimulatorX (MSI)/SimObjects"), QString fsxDir = CSampleUtils::selectDirectory({QStringLiteral("P:/FlightSimulatorX (MSI)/SimObjects"),
QStringLiteral("P:/Temp/SimObjects"), QStringLiteral("P:/Temp/SimObjects"),
QStringLiteral("C:/Flight Simulator 9/Aircraft") QStringLiteral("C:/Flight Simulator 9/Aircraft")
}, streamOut, streamIn); }, streamOut, streamIn);
CAircraftCfgParser cfgParser(CSimulatorInfo(CSimulatorInfo::FSX), fsxDir);
if (!cfgParser.changeRootDirectory(fsxDir)) if (!cfgParser.changeRootDirectory(fsxDir))
{ {
streamOut << "Wrong or empty directoy " << fsxDir << endl; streamOut << "Wrong or empty directoy " << fsxDir << endl;
@@ -56,7 +56,7 @@ namespace BlackSample
} }
streamOut << "Start reading models" << endl; streamOut << "Start reading models" << endl;
cfgParser.startLoading(CAircraftCfgParser::ModeBlocking); cfgParser.startLoading(CAircraftCfgParser::CacheSkipped | CAircraftCfgParser::LoadDirectly);
streamOut << "Read models: " << cfgParser.getAircraftCfgEntriesList().size() << endl; streamOut << "Read models: " << cfgParser.getAircraftCfgEntriesList().size() << endl;
streamOut << "Ambigious models: " << cfgParser.getAircraftCfgEntriesList().detectAmbiguousTitles().join(", ") << endl; streamOut << "Ambigious models: " << cfgParser.getAircraftCfgEntriesList().detectAmbiguousTitles().join(", ") << endl;

View File

@@ -68,7 +68,10 @@ namespace BlackGui
ui->tvp_OwnAircraftModels->setCustomMenu(new CShowSimulatorFile(this), false); ui->tvp_OwnAircraftModels->setCustomMenu(new CShowSimulatorFile(this), false);
ui->tvp_OwnAircraftModels->setCustomMenu(new CMappingOwnSimulatorModelMenu(this)); ui->tvp_OwnAircraftModels->setCustomMenu(new CMappingOwnSimulatorModelMenu(this));
ui->tvp_OwnAircraftModels->setCustomMenu(new CModelStashTools(this, false)); ui->tvp_OwnAircraftModels->setCustomMenu(new CModelStashTools(this, false));
ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(this->m_cachedOwnModels.get()); if (this->m_modelLoader)
{
ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(this->m_modelLoader->getAircraftModels());
}
// how to display forms // how to display forms
ui->editor_AircraftIcao->setSelectOnly(); ui->editor_AircraftIcao->setSelectOnly();
@@ -107,9 +110,9 @@ namespace BlackGui
this->ui->tvp_AircraftModelsForVPilot->setCustomMenu(new CModelStashTools(this, false)); this->ui->tvp_AircraftModelsForVPilot->setCustomMenu(new CModelStashTools(this, false));
this->ui->tvp_AircraftModelsForVPilot->setDisplayAutomatically(true); this->ui->tvp_AircraftModelsForVPilot->setDisplayAutomatically(true);
this->ui->tvp_AircraftModelsForVPilot->addFilterDialog(); this->ui->tvp_AircraftModelsForVPilot->addFilterDialog();
const CAircraftModelList cachedModels(m_cachedVPilotModels.get()); const CAircraftModelList vPilotModels(m_cachedVPilotModels.get());
this->ui->tvp_AircraftModelsForVPilot->updateContainerMaybeAsync(cachedModels); this->ui->tvp_AircraftModelsForVPilot->updateContainerMaybeAsync(vPilotModels);
int noModels = cachedModels.size(); int noModels = vPilotModels.size();
CLogMessage(this).info("%1 cached vPilot models loaded") << noModels; CLogMessage(this).info("%1 cached vPilot models loaded") << noModels;
} }
this->m_vPilot1stInit = false; this->m_vPilot1stInit = false;
@@ -264,7 +267,8 @@ namespace BlackGui
CAircraftModel CDbMappingComponent::getOwnModelForModelString(const QString &modelString) const CAircraftModel CDbMappingComponent::getOwnModelForModelString(const QString &modelString) const
{ {
return m_cachedOwnModels.get().findFirstByModelString(modelString); if (!this->m_modelLoader) { return CAircraftModel(); }
return this->m_modelLoader->getAircraftModels().findFirstByModelString(modelString);
} }
CDbMappingComponent::TabIndex CDbMappingComponent::currentTabIndex() const CDbMappingComponent::TabIndex CDbMappingComponent::currentTabIndex() const
@@ -510,8 +514,9 @@ namespace BlackGui
void CDbMappingComponent::ps_requestOwnModelsUpdate() void CDbMappingComponent::ps_requestOwnModelsUpdate()
{ {
if (!this->m_modelLoader) { return; }
this->ui->tvp_OwnAircraftModels->updateContainerMaybeAsync( this->ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(
this->m_cachedOwnModels.get() this->m_modelLoader->getAircraftModels()
); );
} }
@@ -678,11 +683,7 @@ namespace BlackGui
{ {
const CAircraftModelList models(this->m_modelLoader->getAircraftModels()); const CAircraftModelList models(this->m_modelLoader->getAircraftModels());
CLogMessage(this).info("Loading %1 of models completed") << models.size(); CLogMessage(this).info("Loading %1 of models completed") << models.size();
this->m_cachedOwnModels.set(models); this->ui->tvp_OwnAircraftModels->updateContainerMaybeAsync(models);
CLogMessage(this).info("Written %1 own models to cache") << models.size();
// when the cache writting is done the view vill be updated in the
// cache changed slot
} }
else else
{ {
@@ -692,14 +693,6 @@ namespace BlackGui
this->ui->tvp_OwnAircraftModels->hideLoadIndicator(); this->ui->tvp_OwnAircraftModels->hideLoadIndicator();
} }
void CDbMappingComponent::ps_ownModelsCacheChanged()
{
if (this->ui->tvp_OwnAircraftModels->displayAutomatically())
{
this->ui->tvp_OwnAircraftModels->updateContainer(this->m_cachedOwnModels.get());
}
}
CAircraftModel CDbMappingComponent::getEditorAircraftModel() const CAircraftModel CDbMappingComponent::getEditorAircraftModel() const
{ {
CAircraftModel model(ui->editor_Model->getValue()); CAircraftModel model(ui->editor_Model->getValue());

View File

@@ -181,9 +181,6 @@ namespace BlackGui
//! Model loading finished //! Model loading finished
void ps_onOwnModelsLoadingFinished(bool success); void ps_onOwnModelsLoadingFinished(bool success);
//! Own models cache changed
void ps_ownModelsCacheChanged();
//! Own model count changed //! Own model count changed
void ps_onOwnModelsCountChanged(int count, bool withFilter); void ps_onOwnModelsCountChanged(int count, bool withFilter);
@@ -221,7 +218,6 @@ namespace BlackGui
BlackMisc::Simulation::FsCommon::CVPilotRulesReader m_vPilotReader; //!< read vPilot rules BlackMisc::Simulation::FsCommon::CVPilotRulesReader m_vPilotReader; //!< read vPilot rules
std::unique_ptr<BlackMisc::Simulation::IAircraftModelLoader> m_modelLoader; //!< read own aircraft models std::unique_ptr<BlackMisc::Simulation::IAircraftModelLoader> m_modelLoader; //!< read own aircraft models
BlackMisc::CData<BlackCore::Data::VPilotAircraftModels> m_cachedVPilotModels { this, &CDbMappingComponent::ps_onVPilotCacheChanged }; //!< cache for latest vPilot rules BlackMisc::CData<BlackCore::Data::VPilotAircraftModels> m_cachedVPilotModels { this, &CDbMappingComponent::ps_onVPilotCacheChanged }; //!< cache for latest vPilot rules
BlackMisc::CData<BlackCore::Data::OwnSimulatorAircraftModels> m_cachedOwnModels { this, &CDbMappingComponent::ps_ownModelsCacheChanged }; //!< cache for own installed models
BlackMisc::CData<BlackCore::Data::AuthenticatedDbUser> m_swiftDbUser {this, &CDbMappingComponent::ps_userChanged}; BlackMisc::CData<BlackCore::Data::AuthenticatedDbUser> m_swiftDbUser {this, &CDbMappingComponent::ps_userChanged};
bool m_vPilot1stInit = true; bool m_vPilot1stInit = true;
bool m_withVPilot = false; bool m_withVPilot = false;

View File

@@ -39,6 +39,7 @@ HEADERS += *.h \
$$PWD/simulation/fscommon/*.h \ $$PWD/simulation/fscommon/*.h \
$$PWD/simulation/fsx/*.h \ $$PWD/simulation/fsx/*.h \
$$PWD/simulation/xplane/*.h \ $$PWD/simulation/xplane/*.h \
$$PWD/simulation/data/*.h \
$$PWD/weather/*.h $$PWD/weather/*.h
SOURCES += *.cpp \ SOURCES += *.cpp \
@@ -54,6 +55,7 @@ SOURCES += *.cpp \
$$PWD/simulation/fscommon/*.cpp \ $$PWD/simulation/fscommon/*.cpp \
$$PWD/simulation/fsx/*.cpp \ $$PWD/simulation/fsx/*.cpp \
$$PWD/simulation/xplane/*.cpp \ $$PWD/simulation/xplane/*.cpp \
# $$PWD/simulation/data/*.cpp \
$$PWD/weather/*.cpp $$PWD/weather/*.cpp
win32 { win32 {

View File

@@ -19,15 +19,67 @@ namespace BlackMisc
{ {
namespace Simulation namespace Simulation
{ {
IAircraftModelLoader::IAircraftModelLoader(const CSimulatorInfo &info) : IAircraftModelLoader::IAircraftModelLoader(const CSimulatorInfo &info, const QString &rootDirectory, const QStringList &excludeDirs) :
m_simulatorInfo(info) m_simulatorInfo(info), m_rootDirectory(rootDirectory), m_excludedDirectories(excludeDirs)
{ } {
connect(this, &IAircraftModelLoader::loadingFinished, this, &IAircraftModelLoader::ps_loadFinished);
}
IAircraftModelLoader::~IAircraftModelLoader() IAircraftModelLoader::~IAircraftModelLoader()
{ {
this->gracefulShutdown(); this->gracefulShutdown();
} }
bool IAircraftModelLoader::existsDir(const QString &directory) const
{
if (directory.isEmpty()) { return false; }
QDir dir(directory);
//! \todo not available network dir can make this hang here
return dir.exists();
}
void IAircraftModelLoader::ps_loadFinished(bool success)
{
Q_UNUSED(success);
this->m_loadingInProgress = false;
}
bool IAircraftModelLoader::changeRootDirectory(const QString &directory)
{
if (m_rootDirectory == directory) { return false; }
if (directory.isEmpty() || !existsDir(directory)) { return false; }
m_rootDirectory = directory;
return true;
}
void IAircraftModelLoader::startLoading(LoadMode mode)
{
if (this->m_loadingInProgress) { return; }
this->m_loadingInProgress = true;
const bool useCachedData = !mode.testFlag(CacheSkipped) && this->hasCachedData();
if (useCachedData && mode.testFlag(CacheFirst))
{
emit loadingFinished(true);
return;
}
else if (useCachedData && mode.testFlag(CacheUntilNewer))
{
if (!this->areModelFilesUpdated())
{
emit loadingFinished(true);
return;
}
}
if (mode.testFlag(CacheOnly))
{
// only cache, but we did not find any data
emit loadingFinished(false);
return;
}
this->startLoadingFromDisk(mode);
}
const CSimulatorInfo &IAircraftModelLoader::supportedSimulators() const const CSimulatorInfo &IAircraftModelLoader::supportedSimulators() const
{ {
return m_simulatorInfo; return m_simulatorInfo;
@@ -45,7 +97,8 @@ namespace BlackMisc
void IAircraftModelLoader::cancelLoading() void IAircraftModelLoader::cancelLoading()
{ {
m_cancelLoading = true; this->m_cancelLoading = true;
this->m_loadingInProgress = true;
} }
void IAircraftModelLoader::gracefulShutdown() void IAircraftModelLoader::gracefulShutdown()

View File

@@ -15,6 +15,7 @@
#include "blackmisc/blackmiscexport.h" #include "blackmisc/blackmiscexport.h"
#include "blackmisc/simulation/aircraftmodellist.h" #include "blackmisc/simulation/aircraftmodellist.h"
#include "blackmisc/simulation/simulatorinfo.h" #include "blackmisc/simulation/simulatorinfo.h"
#include "blackmisc/simulation/data/modelcaches.h"
#include "blackmisc/pixmap.h" #include "blackmisc/pixmap.h"
#include <QObject> #include <QObject>
#include <atomic> #include <atomic>
@@ -33,23 +34,45 @@ namespace BlackMisc
public: public:
//! Parser mode //! Parser mode
enum LoadMode enum LoadModeFlag
{ {
ModeBlocking, NotSet = 0,
ModeBackground LoadDirectly = 1 << 0, //!< load syncronously (blocking), normally for testing
LoadInBackground = 1 << 1, //!< load in background, asnycronously
CacheUntilNewer = 1 << 2, //!< use cache until newer data re available
CacheFirst = 1 << 3, //!< always use cache (if it has data)
CacheSkipped = 1 << 4, //!< ignore cache
CacheOnly = 1 << 5, //!< force ignoring the cache
Default = LoadInBackground | CacheFirst //!< default mode
}; };
Q_DECLARE_FLAGS(LoadMode, LoadModeFlag)
//! Destructor //! Destructor
virtual ~IAircraftModelLoader(); virtual ~IAircraftModelLoader();
//! Start the loading process //! Start the loading process from disk
virtual void startLoading(LoadMode mode = ModeBackground) = 0; void startLoading(LoadMode mode = Default);
//! Change the directory
bool changeRootDirectory(const QString &directory);
//! Current root directory
QString getRootDirectory() const { return this->m_rootDirectory; }
//! Loading finished? //! Loading finished?
virtual bool isLoadingFinished() const = 0; virtual bool isLoadingFinished() const = 0;
//! The models loaded //! The loaded models
virtual BlackMisc::Simulation::CAircraftModelList getAircraftModels() const = 0; virtual const BlackMisc::Simulation::CAircraftModelList &getAircraftModels() const = 0;
//! Cache timestamp
virtual QDateTime getCacheTimestamp() const = 0;
//! Model files updated?
virtual bool areModelFilesUpdated() const = 0;
//! Any cached data
virtual bool hasCachedData() const = 0;
//! A representive pixmap for given model //! A representive pixmap for given model
virtual BlackMisc::CPixmap iconForModel(const QString &modelName, BlackMisc::CStatusMessage &statusMessage) const = 0; virtual BlackMisc::CPixmap iconForModel(const QString &modelName, BlackMisc::CStatusMessage &statusMessage) const = 0;
@@ -78,13 +101,30 @@ namespace BlackMisc
protected: protected:
//! Constructor //! Constructor
IAircraftModelLoader(const CSimulatorInfo &info = CSimulatorInfo()); IAircraftModelLoader(const CSimulatorInfo &info, const QString &rootDirectory, const QStringList &excludeDirs = {});
//! Check if directory exists
bool existsDir(const QString &directory) const;
//! Start the loading process from disk
virtual void startLoadingFromDisk(LoadMode mode) = 0;
BlackMisc::Simulation::CSimulatorInfo m_simulatorInfo; //!< Corresponding simulator BlackMisc::Simulation::CSimulatorInfo m_simulatorInfo; //!< Corresponding simulator
std::atomic<bool> m_cancelLoading { false }; //!< flag std::atomic<bool> m_cancelLoading { false }; //!< flag
std::atomic<bool> m_loadingInProgress { false }; //!< Loading in progress
QString m_rootDirectory; //!< root directory parsing aircraft.cfg files
QStringList m_excludedDirectories; //!< directories not to be parsed
protected slots:
//! Loading finished
void ps_loadFinished(bool success);
}; };
} // namespace } // namespace
} // namespace } // namespace
Q_DECLARE_METATYPE(BlackMisc::Simulation::IAircraftModelLoader::LoadMode)
Q_DECLARE_METATYPE(BlackMisc::Simulation::IAircraftModelLoader::LoadModeFlag)
Q_DECLARE_OPERATORS_FOR_FLAGS(BlackMisc::Simulation::IAircraftModelLoader::LoadMode)
#endif // guard #endif // guard

View File

@@ -0,0 +1,67 @@
/* Copyright (C) 2016
* 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_DATA_MODELCACHES
#define BLACKMISC_SIMULATION_DATA_MODELCACHES
#include "blackmisc/datacache.h"
#include "blackmisc/simulation/aircraftmodellist.h"
namespace BlackMisc
{
namespace Simulation
{
namespace Data
{
//! Trait for model cache
struct ModelCache : public BlackMisc::CDataTrait<BlackMisc::Simulation::CAircraftModelList>
{
//! Default value
static const BlackMisc::Simulation::CAircraftModelList &defaultValue()
{
static const BlackMisc::Simulation::CAircraftModelList ml;
return ml;
}
};
//! Trait for XP model cache
struct ModelCacheXP : public ModelCache
{
//! Key in data cache
static const char *key() { return "modelcachexp"; }
};
//! Trait for FSX model cache
struct ModelCacheFsx : public ModelCache
{
//! Key in data cache
static const char *key() { return "modelcachefsx"; }
};
//! Trait for FS9 model cache
struct ModelCacheFs9 : public ModelCache
{
//! Key in data cache
static const char *key() { return "modelcachefs9"; }
};
//! Trait for P3D model cache
struct ModelCacheP3D : public ModelCache
{
//! Key in data cache
static const char *key() { return "modelcachep3d"; }
};
} // ns
} // ns
} // ns
#endif // guard

View File

@@ -9,6 +9,7 @@
#include "aircraftcfgparser.h" #include "aircraftcfgparser.h"
#include "blackmisc/simulation/fscommon/fscommonutil.h" #include "blackmisc/simulation/fscommon/fscommonutil.h"
#include "blackmisc/fileutils.h"
#include "blackmisc/predicates.h" #include "blackmisc/predicates.h"
#include "blackmisc/logmessage.h" #include "blackmisc/logmessage.h"
@@ -23,12 +24,8 @@ namespace BlackMisc
{ {
namespace FsCommon namespace FsCommon
{ {
CAircraftCfgParser::CAircraftCfgParser() { } CAircraftCfgParser::CAircraftCfgParser(const CSimulatorInfo &simInfo, const QString &rootDirectory, const QStringList &excludeDirs) :
IAircraftModelLoader(simInfo, rootDirectory, excludeDirs)
CAircraftCfgParser::CAircraftCfgParser(const CSimulatorInfo &simInfo, const QString &rootDirectory, const QStringList &exludes) :
IAircraftModelLoader(simInfo),
m_rootDirectory(rootDirectory),
m_excludedDirectories(exludes)
{ } { }
std::unique_ptr<CAircraftCfgParser> CAircraftCfgParser::createModelLoader(const CSimulatorInfo &simInfo) std::unique_ptr<CAircraftCfgParser> CAircraftCfgParser::createModelLoader(const CSimulatorInfo &simInfo)
@@ -64,15 +61,6 @@ namespace BlackMisc
if (this->m_parserWorker) { this->m_parserWorker->waitForFinished(); } if (this->m_parserWorker) { this->m_parserWorker->waitForFinished(); }
} }
bool CAircraftCfgParser::changeRootDirectory(const QString &directory)
{
if (m_rootDirectory == directory) { return false; }
if (directory.isEmpty() || !existsDir(directory)) { return false; }
m_rootDirectory = directory;
return true;
}
CPixmap CAircraftCfgParser::iconForModel(const QString &modelString, CStatusMessage &statusMessage) const CPixmap CAircraftCfgParser::iconForModel(const QString &modelString, CStatusMessage &statusMessage) const
{ {
static const CPixmap empty {}; static const CPixmap empty {};
@@ -101,13 +89,13 @@ namespace BlackMisc
return empty; return empty;
} }
void CAircraftCfgParser::startLoading(LoadMode mode) void CAircraftCfgParser::startLoadingFromDisk(LoadMode mode)
{ {
if (mode == ModeBackground) if (mode.testFlag(LoadInBackground))
{ {
if (m_parserWorker && !m_parserWorker->isFinished()) { return; } if (m_parserWorker && !m_parserWorker->isFinished()) { return; }
auto rootDirectory = m_rootDirectory; const QString rootDirectory(m_rootDirectory); // copy
auto excludedDirectories = m_excludedDirectories; const QStringList excludedDirectories(m_excludedDirectories); // copy
m_parserWorker = BlackMisc::CWorker::fromTask(this, "CAircraftCfgParser::changeDirectory", m_parserWorker = BlackMisc::CWorker::fromTask(this, "CAircraftCfgParser::changeDirectory",
[this, rootDirectory, excludedDirectories]() [this, rootDirectory, excludedDirectories]()
{ {
@@ -117,13 +105,18 @@ namespace BlackMisc
}); });
m_parserWorker->thenWithResult<std::pair<CAircraftCfgEntriesList, bool>>(this, [this](const auto &pair) m_parserWorker->thenWithResult<std::pair<CAircraftCfgEntriesList, bool>>(this, [this](const auto &pair)
{ {
if (pair.second) { this->updateCfgEntriesList(pair.first); } if (pair.second)
{
this->updateCfgEntriesList(pair.first);
this->setModelsInCache(pair.first.toAircraftModelList());
}
}); });
} }
else if (mode == ModeBlocking) else if (mode == LoadDirectly)
{ {
bool ok; bool ok;
m_parsedCfgEntriesList = performParsing(m_rootDirectory, m_excludedDirectories, &ok); this->m_parsedCfgEntriesList = performParsing(m_rootDirectory, m_excludedDirectories, &ok);
this->setModelsInCache(this->m_parsedCfgEntriesList.toAircraftModelList());
emit loadingFinished(ok); emit loadingFinished(ok);
} }
} }
@@ -133,11 +126,68 @@ namespace BlackMisc
return !m_parserWorker || m_parserWorker->isFinished(); return !m_parserWorker || m_parserWorker->isFinished();
} }
CAircraftModelList CAircraftCfgParser::getAircraftModels() const QDateTime CAircraftCfgParser::getCacheTimestamp() const
{ {
return getAircraftCfgEntriesList().toAircraftModelList(this->m_simulatorInfo); if (this->m_simulatorInfo.fsx())
{
return m_modelCacheFsx.getTimestamp();
}
else if (this->m_simulatorInfo.fs9())
{
return m_modelCacheFs9.getTimestamp();
}
else if (this->m_simulatorInfo.p3d())
{
return m_modelCacheP3D.getTimestamp();
}
Q_ASSERT_X(false, Q_FUNC_INFO, "Illegal simulator info");
return QDateTime();
} }
bool CAircraftCfgParser::areModelFilesUpdated() const
{
const QDateTime cacheTs(getCacheTimestamp());
if (!cacheTs.isValid()) { return true; }
//! \todo KB we cannot use the exclude dirs, a minor disadvantege. Also wonder if it was better to parse a QStringList ofr wildcard
return CFileUtils::containsFileNewerThan(cacheTs, this->getRootDirectory(), true, "*.cfg");
}
bool CAircraftCfgParser::hasCachedData() const
{
if (this->m_simulatorInfo.fsx())
{
return !m_modelCacheFsx.get().isEmpty();
}
else if (this->m_simulatorInfo.fs9())
{
return !m_modelCacheFs9.get().isEmpty();
}
else if (this->m_simulatorInfo.p3d())
{
return !m_modelCacheP3D.get().isEmpty();
}
Q_ASSERT_X(false, Q_FUNC_INFO, "Illegal simulator info");
return false;
}
const CAircraftModelList &CAircraftCfgParser::getAircraftModels() const
{
static const CAircraftModelList empty;
if (this->m_simulatorInfo.fsx())
{
return m_modelCacheFsx.get();
}
else if (this->m_simulatorInfo.fs9())
{
return m_modelCacheFs9.get();
}
else if (this->m_simulatorInfo.p3d())
{
return m_modelCacheP3D.get();
}
Q_ASSERT_X(false, Q_FUNC_INFO, "Illegal simulator info");
return empty;
}
void CAircraftCfgParser::updateCfgEntriesList(const CAircraftCfgEntriesList &cfgEntriesList) void CAircraftCfgParser::updateCfgEntriesList(const CAircraftCfgEntriesList &cfgEntriesList)
{ {
@@ -145,6 +195,24 @@ namespace BlackMisc
emit loadingFinished(true); emit loadingFinished(true);
} }
CStatusMessage CAircraftCfgParser::setModelsInCache(const CAircraftModelList &models)
{
if (this->m_simulatorInfo.fsx())
{
return m_modelCacheFsx.set(models);
}
else if (this->m_simulatorInfo.fs9())
{
return m_modelCacheFs9.set(models);
}
else if (this->m_simulatorInfo.p3d())
{
return m_modelCacheP3D.set(models);
}
Q_ASSERT_X(false, Q_FUNC_INFO, "Illegal simulator info");
return CStatusMessage(this, CStatusMessage::SeverityError, "Wrong simulator type");
}
CAircraftCfgEntriesList CAircraftCfgParser::performParsing(const QString &directory, const QStringList &excludeDirectories, bool *ok) CAircraftCfgEntriesList CAircraftCfgParser::performParsing(const QString &directory, const QStringList &excludeDirectories, bool *ok)
{ {
// //
@@ -205,7 +273,7 @@ namespace BlackMisc
// remark: in a 1st version I have used QSettings to parse to file as ini file // remark: in a 1st version I have used QSettings to parse to file as ini file
// unfortunately some files are malformed which could end up in wrong data // unfortunately some files are malformed which could end up in wrong data
QString fileName = file.absoluteFilePath(); const QString fileName = file.absoluteFilePath();
QFile file(fileName); QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text)) if (!file.open(QFile::ReadOnly | QFile::Text))
{ {
@@ -335,14 +403,6 @@ namespace BlackMisc
return result; return result;
} }
bool CAircraftCfgParser::existsDir(const QString &directory) const
{
if (directory.isEmpty()) { return false; }
QDir dir(directory);
//! \todo not available network dir can make this hang here
return dir.exists();
}
QString CAircraftCfgParser::fixedStringContent(const QSettings &settings, const QString &key) QString CAircraftCfgParser::fixedStringContent(const QSettings &settings, const QString &key)
{ {
return fixedStringContent(settings.value(key)); return fixedStringContent(settings.value(key));

View File

@@ -15,8 +15,10 @@
#include "blackmisc/blackmiscexport.h" #include "blackmisc/blackmiscexport.h"
#include "blackmisc/worker.h" #include "blackmisc/worker.h"
#include "blackmisc/pixmap.h" #include "blackmisc/pixmap.h"
#include "blackmisc/datacache.h"
#include "blackmisc/simulation/aircraftmodelloader.h" #include "blackmisc/simulation/aircraftmodelloader.h"
#include "blackmisc/simulation/fscommon/aircraftcfgentrieslist.h" #include "blackmisc/simulation/fscommon/aircraftcfgentrieslist.h"
#include "blackmisc/simulation/data/modelcaches.h"
#include <QPointer> #include <QPointer>
@@ -32,35 +34,24 @@ namespace BlackMisc
Q_OBJECT Q_OBJECT
public: public:
//! Destructor
CAircraftCfgParser();
//! Constructor //! Constructor
CAircraftCfgParser(const BlackMisc::Simulation::CSimulatorInfo &simInfo, const QString &rootDirectory, const QStringList &exludes = {}); CAircraftCfgParser(const BlackMisc::Simulation::CSimulatorInfo &simInfo, const QString &rootDirectory, const QStringList &exludes = {});
//! Virtual destructor //! Virtual destructor
virtual ~CAircraftCfgParser(); virtual ~CAircraftCfgParser();
//! Change the directory
bool changeRootDirectory(const QString &directory);
//! Current root directory
QString getRootDirectory() const { return this->m_rootDirectory; }
//! Get parsed aircraft cfg entries list //! Get parsed aircraft cfg entries list
const CAircraftCfgEntriesList &getAircraftCfgEntriesList() const { return m_parsedCfgEntriesList; } const CAircraftCfgEntriesList &getAircraftCfgEntriesList() const { return m_parsedCfgEntriesList; }
//! \copydoc IAircraftModelLoader::iconForModel //! \name Interface functions
//! @{
virtual BlackMisc::CPixmap iconForModel(const QString &modelName, BlackMisc::CStatusMessage &statusMessage) const override; virtual BlackMisc::CPixmap iconForModel(const QString &modelName, BlackMisc::CStatusMessage &statusMessage) const override;
//! \copydoc IAircraftModelLoader::startLoading
virtual void startLoading(LoadMode mode = ModeBackground) override;
//! \copydoc IAircraftModelLoader::isLoadingFinished
virtual bool isLoadingFinished() const override; virtual bool isLoadingFinished() const override;
virtual bool areModelFilesUpdated() const override;
//! \copydoc IAircraftModelLoader::getAircraftModels virtual bool hasCachedData() const override;
virtual BlackMisc::Simulation::CAircraftModelList getAircraftModels() const override; virtual QDateTime getCacheTimestamp() const override;
virtual const BlackMisc::Simulation::CAircraftModelList &getAircraftModels() const override;
//! @}
//! Create an parser object for given simulator //! Create an parser object for given simulator
static std::unique_ptr<CAircraftCfgParser> createModelLoader(const BlackMisc::Simulation::CSimulatorInfo &simInfo); static std::unique_ptr<CAircraftCfgParser> createModelLoader(const BlackMisc::Simulation::CSimulatorInfo &simInfo);
@@ -69,6 +60,15 @@ namespace BlackMisc
//! Parsed or injected entires //! Parsed or injected entires
void updateCfgEntriesList(const BlackMisc::Simulation::FsCommon::CAircraftCfgEntriesList &cfgEntriesList); void updateCfgEntriesList(const BlackMisc::Simulation::FsCommon::CAircraftCfgEntriesList &cfgEntriesList);
protected:
//! Set cached values
BlackMisc::CStatusMessage setModelsInCache(const BlackMisc::Simulation::CAircraftModelList &models);
//! \name Interface functions
//! @{
virtual void startLoadingFromDisk(LoadMode mode) override;
//! @}
private: private:
//! Section within file //! Section within file
enum FileSection enum FileSection
@@ -78,9 +78,6 @@ namespace BlackMisc
Unknown Unknown
}; };
//! Does the directory exist?
bool existsDir(const QString &directory = "") const;
//! Perform the parsing //! Perform the parsing
//! \threadsafe //! \threadsafe
CAircraftCfgEntriesList performParsing(const QString &directory, const QStringList &excludeDirectories, bool *ok); CAircraftCfgEntriesList performParsing(const QString &directory, const QStringList &excludeDirectories, bool *ok);
@@ -94,10 +91,13 @@ namespace BlackMisc
//! Content after "=" //! Content after "="
static QString getFixedIniLineContent(const QString &line); static QString getFixedIniLineContent(const QString &line);
QString m_rootDirectory; //!< root directory parsing aircraft.cfg files
QStringList m_excludedDirectories; //!< directories not to be parsed
CAircraftCfgEntriesList m_parsedCfgEntriesList; //!< parsed entries CAircraftCfgEntriesList m_parsedCfgEntriesList; //!< parsed entries
QPointer<BlackMisc::CWorker> m_parserWorker; //!< worker will destroy itself, so weak pointer QPointer<BlackMisc::CWorker> m_parserWorker; //!< worker will destroy itself, so weak pointer
//! \todo KB/MS Is there nothing better than having 3 cache members
BlackMisc::CData<BlackMisc::Simulation::Data::ModelCacheFsx> m_modelCacheFsx {this}; //!< FSX cache
BlackMisc::CData<BlackMisc::Simulation::Data::ModelCacheFs9> m_modelCacheFs9 {this}; //!< Fs9 cache
BlackMisc::CData<BlackMisc::Simulation::Data::ModelCacheP3D> m_modelCacheP3D {this}; //!< P3D cache
}; };
} // namespace } // namespace
} // namespace } // namespace

View File

@@ -11,6 +11,7 @@
#include "xplaneutil.h" #include "xplaneutil.h"
#include "blackmisc/predicates.h" #include "blackmisc/predicates.h"
#include "blackmisc/logmessage.h" #include "blackmisc/logmessage.h"
#include "blackmisc/fileutils.h"
#include <QDirIterator> #include <QDirIterator>
#include <QTextStream> #include <QTextStream>
@@ -43,13 +44,8 @@ namespace BlackMisc
} }
} }
CAircraftModelLoaderXPlane::CAircraftModelLoaderXPlane() CAircraftModelLoaderXPlane::CAircraftModelLoaderXPlane(const CSimulatorInfo &simInfo, const QString &rootDirectory, const QStringList &excludeDirs) :
{ } IAircraftModelLoader(simInfo, rootDirectory, excludeDirs)
CAircraftModelLoaderXPlane::CAircraftModelLoaderXPlane(const CSimulatorInfo &simInfo, const QString &rootDirectory, const QStringList &exludes) :
IAircraftModelLoader(simInfo),
m_rootDirectory(rootDirectory),
m_excludedDirectories(exludes)
{ } { }
CAircraftModelLoaderXPlane::~CAircraftModelLoaderXPlane() CAircraftModelLoaderXPlane::~CAircraftModelLoaderXPlane()
@@ -58,15 +54,6 @@ namespace BlackMisc
if (this->m_parserWorker) { this->m_parserWorker->waitForFinished(); } if (this->m_parserWorker) { this->m_parserWorker->waitForFinished(); }
} }
bool CAircraftModelLoaderXPlane::changeRootDirectory(const QString &directory)
{
if (m_rootDirectory == directory) { return false; }
if (directory.isEmpty() || !existsDir(directory)) { return false; }
m_rootDirectory = directory;
return true;
}
CPixmap CAircraftModelLoaderXPlane::iconForModel(const QString &modelString, CStatusMessage &statusMessage) const CPixmap CAircraftModelLoaderXPlane::iconForModel(const QString &modelString, CStatusMessage &statusMessage) const
{ {
// X-Plane does not have previews. Maybe we can just use the textures? // X-Plane does not have previews. Maybe we can just use the textures?
@@ -75,7 +62,7 @@ namespace BlackMisc
return {}; return {};
} }
void CAircraftModelLoaderXPlane::startLoading(LoadMode mode) void CAircraftModelLoaderXPlane::startLoadingFromDisk(LoadMode mode)
{ {
m_installedModels.clear(); m_installedModels.clear();
if (m_rootDirectory.isEmpty()) if (m_rootDirectory.isEmpty())
@@ -84,7 +71,7 @@ namespace BlackMisc
return; return;
} }
if (mode == ModeBackground) if (mode.testFlag(LoadInBackground))
{ {
if (m_parserWorker && !m_parserWorker->isFinished()) { return; } if (m_parserWorker && !m_parserWorker->isFinished()) { return; }
auto rootDirectory = m_rootDirectory; auto rootDirectory = m_rootDirectory;
@@ -100,7 +87,7 @@ namespace BlackMisc
this->updateInstalledModels(models); this->updateInstalledModels(models);
}); });
} }
else if (mode == ModeBlocking) else if (mode.testFlag(LoadDirectly))
{ {
m_installedModels = performParsing(m_rootDirectory, m_excludedDirectories); m_installedModels = performParsing(m_rootDirectory, m_excludedDirectories);
emit loadingFinished(true); emit loadingFinished(true);
@@ -112,7 +99,27 @@ namespace BlackMisc
return !m_parserWorker || m_parserWorker->isFinished(); return !m_parserWorker || m_parserWorker->isFinished();
} }
CAircraftModelList CAircraftModelLoaderXPlane::getAircraftModels() const bool CAircraftModelLoaderXPlane::areModelFilesUpdated() const
{
const QDateTime cacheTs(getCacheTimestamp());
if (!cacheTs.isValid()) { return true; }
//! \todo KB we cannot use the exclude dirs, a minor disadvantege. Also wonder if it was better to parse a QStringList ofr wildcard
return CFileUtils::containsFileNewerThan(cacheTs, this->getRootDirectory(), true, "xsb_aircraft.txt");
}
bool CAircraftModelLoaderXPlane::hasCachedData() const
{
//! \todo KB
return false;
}
QDateTime CAircraftModelLoaderXPlane::getCacheTimestamp() const
{
//! \todo KB add cache and report back
return QDateTime();
}
const CAircraftModelList &CAircraftModelLoaderXPlane::getAircraftModels() const
{ {
return m_installedModels; return m_installedModels;
} }
@@ -216,7 +223,6 @@ namespace BlackMisc
m_cslPackages.clear(); m_cslPackages.clear();
QDir searchPath(rootDirectory, "xsb_aircraft.txt"); QDir searchPath(rootDirectory, "xsb_aircraft.txt");
QDirIterator it(searchPath, QDirIterator::Subdirectories); QDirIterator it(searchPath, QDirIterator::Subdirectories);
while (it.hasNext()) while (it.hasNext())
@@ -282,14 +288,6 @@ namespace BlackMisc
return installedModels; return installedModels;
} }
bool CAircraftModelLoaderXPlane::existsDir(const QString &directory) const
{
if (directory.isEmpty()) { return false; }
QDir dir(directory);
//! \todo not available network dir can make this hang here
return dir.exists();
}
bool CAircraftModelLoaderXPlane::doPackageSub(QString &ioPath) bool CAircraftModelLoaderXPlane::doPackageSub(QString &ioPath)
{ {
for (auto i = m_cslPackages.begin(); i != m_cslPackages.end(); ++i) for (auto i = m_cslPackages.begin(); i != m_cslPackages.end(); ++i)

View File

@@ -35,37 +35,32 @@ namespace BlackMisc
Q_OBJECT Q_OBJECT
public: public:
//! Constructor
CAircraftModelLoaderXPlane();
//! Constructor //! Constructor
CAircraftModelLoaderXPlane(const BlackMisc::Simulation::CSimulatorInfo &simInfo, const QString &rootDirectory, const QStringList &exludes = {}); CAircraftModelLoaderXPlane(const BlackMisc::Simulation::CSimulatorInfo &simInfo, const QString &rootDirectory, const QStringList &exludes = {});
//! Virtual destructor //! Virtual destructor
virtual ~CAircraftModelLoaderXPlane(); virtual ~CAircraftModelLoaderXPlane();
//! Change the directory //! \name Interface functions
bool changeRootDirectory(const QString &directory); //! @{
//! Current root directory
QString getRootDirectory() const { return this->m_rootDirectory; }
//! \copydoc IAircraftModelLoader::iconForModel
virtual BlackMisc::CPixmap iconForModel(const QString &modelName, BlackMisc::CStatusMessage &statusMessage) const override; virtual BlackMisc::CPixmap iconForModel(const QString &modelName, BlackMisc::CStatusMessage &statusMessage) const override;
//! \copydoc IAircraftModelLoader::startLoading
virtual void startLoading(LoadMode mode = ModeBackground) override;
//! \copydoc IAircraftModelLoader::isLoadingFinished
virtual bool isLoadingFinished() const override; virtual bool isLoadingFinished() const override;
virtual bool areModelFilesUpdated() const override;
//! \copydoc IAircraftModelLoader::getAircraftModels virtual bool hasCachedData() const override;
virtual BlackMisc::Simulation::CAircraftModelList getAircraftModels() const override; virtual QDateTime getCacheTimestamp() const override;
virtual const BlackMisc::Simulation::CAircraftModelList &getAircraftModels() const override;
//! @}
public slots: public slots:
//! Parsed or injected models //! Parsed or injected models
void updateInstalledModels(const BlackMisc::Simulation::CAircraftModelList &models); void updateInstalledModels(const BlackMisc::Simulation::CAircraftModelList &models);
protected:
//! \name Interface functions
//! @{
virtual void startLoadingFromDisk(LoadMode mode) override;
//! @}
private: private:
struct CSLPlane struct CSLPlane
{ {
@@ -98,8 +93,6 @@ namespace BlackMisc
BlackMisc::Simulation::CAircraftModelList parseFlyableAirplanes(const QString &rootDirectory, const QStringList &excludeDirectories); BlackMisc::Simulation::CAircraftModelList parseFlyableAirplanes(const QString &rootDirectory, const QStringList &excludeDirectories);
BlackMisc::Simulation::CAircraftModelList parseCslPackages(const QString &rootDirectory, const QStringList &excludeDirectories); BlackMisc::Simulation::CAircraftModelList parseCslPackages(const QString &rootDirectory, const QStringList &excludeDirectories);
//! Does the directory exist?
bool existsDir(const QString &directory = QString()) const;
bool doPackageSub(QString &ioPath); bool doPackageSub(QString &ioPath);
bool parseExportCommand(const QStringList &tokens, CSLPackage &package, const QString &path, int lineNum); bool parseExportCommand(const QStringList &tokens, CSLPackage &package, const QString &path, int lineNum);
@@ -118,8 +111,6 @@ namespace BlackMisc
CSLPackage parsePackageHeader(const QString &path, const QString &content); CSLPackage parsePackageHeader(const QString &path, const QString &content);
void parseFullPackage(const QString &content, CSLPackage &package); void parseFullPackage(const QString &content, CSLPackage &package);
QString m_rootDirectory; //!< root directory parsing aircraft.cfg files
QStringList m_excludedDirectories; //!< directories not to be parsed
QPointer<BlackMisc::CWorker> m_parserWorker; //!< worker will destroy itself, so weak pointer QPointer<BlackMisc::CWorker> m_parserWorker; //!< worker will destroy itself, so weak pointer
QVector<CSLPackage> m_cslPackages; //!< Parsed Packages. No lock required since accessed only from one thread QVector<CSLPackage> m_cslPackages; //!< Parsed Packages. No lock required since accessed only from one thread
BlackMisc::Simulation::CAircraftModelList m_installedModels; BlackMisc::Simulation::CAircraftModelList m_installedModels;

View File

@@ -52,7 +52,7 @@ namespace BlackSimPlugin
} }
else else
{ {
m_aircraftCfgParser->startLoading(CAircraftCfgParser::ModeBackground); m_aircraftCfgParser->startLoading(CAircraftCfgParser::LoadInBackground);
} }
// //
// reading from cache / settings would go here // reading from cache / settings would go here