Allow to update model directories

This commit is contained in:
Klaus Basan
2019-05-03 16:55:58 +02:00
parent 71fbe5b604
commit 3be753a6a7
9 changed files with 163 additions and 24 deletions

View File

@@ -200,6 +200,56 @@ namespace BlackCore
return consolidatedModels; return consolidatedModels;
} }
CAircraftModelList CDatabaseUtils::updateModelsDirectoriesAllowsGuiRefresh(const CAircraftModelList &models, const CAircraftModelList &simulatorModels, QStringList &removedModelStrings, bool processEvents)
{
if (models.isEmpty() || simulatorModels.isEmpty()) { return models; }
QTime timer;
timer.start();
const QSet<QString> allOwnModelsModelStrings = simulatorModels.getModelStringSet();
CAircraftModelList consolidatedModels;
removedModelStrings.clear();
int c = 0;
for (const CAircraftModel &model : models)
{
c++;
if (processEvents && c % 125 == 0)
{
if (!sApp || sApp->isShuttingDown()) { return models; }
sApp->processEventsFor(25);
}
const QString ms(model.getModelString());
if (ms.isEmpty()) { continue; }
if (!allOwnModelsModelStrings.contains(ms))
{
removedModelStrings.push_back(ms);
continue;
}
CAircraftModel consolidated = simulatorModels.findFirstByModelStringAliasOrDefault(ms);
if (consolidated.hasModelString())
{
if (consolidated.hasExistingCorrespondingFile())
{
// update by existing one
consolidatedModels.push_back(consolidated);
}
else
{
// keep
consolidatedModels.push_back(model);
}
}
else
{
consolidatedModels.push_back(model);
}
}
CLogMessage(static_cast<CDatabaseUtils *>(nullptr)).info(u"Updated directories %1 vs. %2 in %3 ms") << models.size() << simulatorModels.size() << timer.elapsed() << "ms";
return consolidatedModels;
}
int CDatabaseUtils::consolidateModelsWithDbDataAllowsGuiRefresh(CAircraftModelList &models, bool force, bool processEvents) int CDatabaseUtils::consolidateModelsWithDbDataAllowsGuiRefresh(CAircraftModelList &models, bool force, bool processEvents)
{ {
QTime timer; QTime timer;

View File

@@ -38,6 +38,10 @@ namespace BlackCore
//! \remark kept here with the other consolidate functions, but actually DB independent //! \remark kept here with the other consolidate functions, but actually DB independent
static BlackMisc::Simulation::CAircraftModelList consolidateModelsWithSimulatorModelsAllowsGuiRefresh(const BlackMisc::Simulation::CAircraftModelList &models, const BlackMisc::Simulation::CAircraftModelList &simulatorModels, QStringList &removedModelStrings, bool processEvents); static BlackMisc::Simulation::CAircraftModelList consolidateModelsWithSimulatorModelsAllowsGuiRefresh(const BlackMisc::Simulation::CAircraftModelList &models, const BlackMisc::Simulation::CAircraftModelList &simulatorModels, QStringList &removedModelStrings, bool processEvents);
//! Update directories in models with simulator model data (aka "models on disk")
//! \remark kept here with the other consolidate functions, but actually DB independent
static BlackMisc::Simulation::CAircraftModelList updateModelsDirectoriesAllowsGuiRefresh(const BlackMisc::Simulation::CAircraftModelList &models, const BlackMisc::Simulation::CAircraftModelList &simulatorModels, QStringList &removedModelStrings, bool processEvents);
//! Consolidate own (aircraft) model data with DB data //! Consolidate own (aircraft) model data with DB data
static BlackMisc::Simulation::CAircraftModel consolidateOwnAircraftModelWithDbData(const BlackMisc::Simulation::CAircraftModel &model, bool force, bool *modified = nullptr); static BlackMisc::Simulation::CAircraftModel consolidateOwnAircraftModelWithDbData(const BlackMisc::Simulation::CAircraftModel &model, bool force, bool *modified = nullptr);

View File

@@ -100,7 +100,7 @@ namespace BlackGui
} }
} }
if (m_messageFrame && !model.getIconPath().isEmpty()) if (m_messageFrame && !model.getIconFile().isEmpty())
{ {
added = true; added = true;
menuActions.addMenuSimulator(); menuActions.addMenuSimulator();
@@ -133,7 +133,7 @@ namespace BlackGui
const CAircraftModelView *mv = modelView(); const CAircraftModelView *mv = modelView();
if (!mv->hasSingleSelectedRow()) { return; } if (!mv->hasSingleSelectedRow()) { return; }
const CAircraftModel model(mv->selectedObject()); const CAircraftModel model(mv->selectedObject());
if (model.getIconPath().isEmpty()) { return; } if (model.getIconFile().isEmpty()) { return; }
CStatusMessage msg(this); CStatusMessage msg(this);
const CPixmap pm(model.loadIcon(msg)); const CPixmap pm(model.loadIcon(msg));
if (msg.isSuccess()) if (msg.isSuccess())
@@ -288,11 +288,14 @@ namespace BlackGui
menuActions.addMenuConsolidateModels(); menuActions.addMenuConsolidateModels();
// consolidate
m_consolidateAll = menuActions.addAction(m_consolidateAll, CIcons::appModels16(), "All with simulator models", CMenuAction::pathModelConsolidate(), { this, &CConsolidateWithSimulatorModels::consolidateData }); m_consolidateAll = menuActions.addAction(m_consolidateAll, CIcons::appModels16(), "All with simulator models", CMenuAction::pathModelConsolidate(), { this, &CConsolidateWithSimulatorModels::consolidateData });
if (mv->hasSelection()) if (mv->hasSelection()) { m_consolidateSelected = menuActions.addAction(m_consolidateSelected, CIcons::appModels16(), "Selected with simulator models", CMenuAction::pathModelConsolidate(), { this, &CConsolidateWithSimulatorModels::consolidateSelectedData }); }
{
m_consolidateSelected = menuActions.addAction(m_consolidateSelected, CIcons::appModels16(), "Selected with simulator models", CMenuAction::pathModelConsolidate(), { this, &CConsolidateWithSimulatorModels::consolidateSelectedData }); // update directories
} m_updateDirsAll = menuActions.addAction(m_updateDirsAll, CIcons::disk16(), "Update all directories", CMenuAction::pathModelConsolidate(), { this, &CConsolidateWithSimulatorModels::updateDirectoryData });
if (mv->hasSelection()) { m_updateDirsSelected = menuActions.addAction(m_updateDirsSelected, CIcons::disk16(), "Update directories for selected", CMenuAction::pathModelConsolidate(), { this, &CConsolidateWithSimulatorModels::updateDirectorySelectedData }); }
this->nestedCustomMenu(menuActions); this->nestedCustomMenu(menuActions);
} }
@@ -354,6 +357,64 @@ namespace BlackGui
} }
} }
void CConsolidateWithSimulatorModels::updateDirectoryData()
{
bool filtered = false;
const CAircraftModelList models(this->getAllOrAllFilteredAircraftModels(&filtered));
if (models.isEmpty()) { return; }
QStringList removedModelStrings;
const int i = this->modelView()->showLoadIndicator();
const CAircraftModelList consolidated = CDatabaseUtils::updateModelsDirectoriesAllowsGuiRefresh(models, this->getSimulatorModels(), removedModelStrings, true);
const CSimulatorInfo sim(this->getSimulator());
if (!filtered)
{
this->modelsTargetSetable()->setModelsForSimulator(consolidated, sim);
}
else
{
if (!this->modelsTargetUpdatable())
{
CLogMessage(this).warning(u"No updatable target");
}
else
{
this->modelsTargetUpdatable()->updateModelsForSimulator(consolidated, sim);
}
}
this->modelView()->hideLoadIndicator(i);
if (!removedModelStrings.isEmpty() && this->getMappingComponent())
{
const CStatusMessage m = CStatusMessage(this).info(u"Removed %1 model(s)") << removedModelStrings.size();
this->getMappingComponent()->showOverlayMessage(m, 5000);
}
}
void CConsolidateWithSimulatorModels::updateDirectorySelectedData()
{
Q_ASSERT_X(sGui, Q_FUNC_INFO, "Missing sGui");
const CAircraftModelList models(this->getSelectedAircraftModels());
if (models.isEmpty()) { return; }
if (!this->modelsTargetUpdatable())
{
CLogMessage(this).warning(u"No updatable target");
return;
}
QStringList removedModelStrings;
const int i = this->modelView()->showLoadIndicator();
const CAircraftModelList consolidated = CDatabaseUtils::updateModelsDirectoriesAllowsGuiRefresh(models, this->getSimulatorModels(), removedModelStrings, true);
const CSimulatorInfo sim(this->getSimulator());
this->modelsTargetUpdatable()->updateModelsForSimulator(consolidated, sim);
this->modelView()->hideLoadIndicator(i);
if (!removedModelStrings.isEmpty() && this->getMappingComponent())
{
const CStatusMessage m = CStatusMessage(this).info(u"Removed %1 model(s)") << removedModelStrings.size();
this->getMappingComponent()->showOverlayMessage(m, 5000);
}
}
CAircraftModelList CConsolidateWithSimulatorModels::getSimulatorModels() const CAircraftModelList CConsolidateWithSimulatorModels::getSimulatorModels() const
{ {
CDbMappingComponent *mc = this->getMappingComponent(); CDbMappingComponent *mc = this->getMappingComponent();

View File

@@ -112,7 +112,7 @@ namespace BlackGui
QAction *m_consolidateSelected = nullptr; //!< consolidate data with DB (selected) QAction *m_consolidateSelected = nullptr; //!< consolidate data with DB (selected)
}; };
//! Merge with simulator models (e.g. remove no longer existing models) //! Merge/update with simulator models (e.g. remove no longer existing models)
class CConsolidateWithSimulatorModels : public IAircraftModelViewMenu class CConsolidateWithSimulatorModels : public IAircraftModelViewMenu
{ {
Q_OBJECT Q_OBJECT
@@ -136,6 +136,8 @@ namespace BlackGui
private: private:
void consolidateData(); void consolidateData();
void consolidateSelectedData(); void consolidateSelectedData();
void updateDirectoryData();
void updateDirectorySelectedData();
//! Get models //! Get models
BlackMisc::Simulation::CAircraftModelList getSimulatorModels() const; BlackMisc::Simulation::CAircraftModelList getSimulatorModels() const;
@@ -151,6 +153,8 @@ namespace BlackGui
QObject *m_modelsTarget = nullptr; //!< optional target for setting/updating the models QObject *m_modelsTarget = nullptr; //!< optional target for setting/updating the models
QAction *m_consolidateAll = nullptr; //!< consolidate data with DB (all) QAction *m_consolidateAll = nullptr; //!< consolidate data with DB (all)
QAction *m_consolidateSelected = nullptr; //!< consolidate data with DB (selected) QAction *m_consolidateSelected = nullptr; //!< consolidate data with DB (selected)
QAction *m_updateDirsAll = nullptr; //!< consolidate file name/dir (all)
QAction *m_updateDirsSelected = nullptr; //!< consolidate file name/dir (selected)
}; };
} // ns } // ns
} // ns } // ns

View File

@@ -258,7 +258,7 @@ namespace BlackMisc
case IndexSupportedParts: return CVariant(m_supportedParts); case IndexSupportedParts: return CVariant(m_supportedParts);
case IndexFileTimestamp: return CVariant::fromValue(this->getFileTimestamp()); case IndexFileTimestamp: return CVariant::fromValue(this->getFileTimestamp());
case IndexFileTimestampFormattedYmdhms: return CVariant::fromValue(this->getFormattedFileTimestampYmdhms()); case IndexFileTimestampFormattedYmdhms: return CVariant::fromValue(this->getFormattedFileTimestampYmdhms());
case IndexIconPath: return CVariant(m_iconPath); case IndexIconPath: return CVariant(m_iconFile);
case IndexAircraftIcaoCode: return m_aircraftIcao.propertyByIndex(index.copyFrontRemoved()); case IndexAircraftIcaoCode: return m_aircraftIcao.propertyByIndex(index.copyFrontRemoved());
case IndexLivery: return m_livery.propertyByIndex(index.copyFrontRemoved()); case IndexLivery: return m_livery.propertyByIndex(index.copyFrontRemoved());
case IndexCallsign: return m_callsign.propertyByIndex(index.copyFrontRemoved()); case IndexCallsign: return m_callsign.propertyByIndex(index.copyFrontRemoved());
@@ -284,7 +284,7 @@ namespace BlackMisc
case IndexDescription: m_description = variant.toQString(); break; case IndexDescription: m_description = variant.toQString(); break;
case IndexSimulatorInfo: m_simulator.setPropertyByIndex(index.copyFrontRemoved(), variant); break; case IndexSimulatorInfo: m_simulator.setPropertyByIndex(index.copyFrontRemoved(), variant); break;
case IndexName: m_name = variant.toQString(); break; case IndexName: m_name = variant.toQString(); break;
case IndexIconPath: m_iconPath = variant.toQString(); break; case IndexIconPath: m_iconFile = variant.toQString(); break;
case IndexCG: m_cg.setPropertyByIndex(index.copyFrontRemoved(), variant); break; case IndexCG: m_cg.setPropertyByIndex(index.copyFrontRemoved(), variant); break;
case IndexSupportedParts: this->setSupportedParts(variant.toQString()); break; case IndexSupportedParts: this->setSupportedParts(variant.toQString()); break;
case IndexModelType: m_modelType = variant.value<ModelType>(); break; case IndexModelType: m_modelType = variant.value<ModelType>(); break;
@@ -345,7 +345,7 @@ namespace BlackMisc
case IndexName: return m_name.compare(compareValue.getName(), Qt::CaseInsensitive); case IndexName: return m_name.compare(compareValue.getName(), Qt::CaseInsensitive);
case IndexCallsign: return m_callsign.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getCallsign()); case IndexCallsign: return m_callsign.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getCallsign());
case IndexFileName: return m_fileName.compare(compareValue.getFileName(), Qt::CaseInsensitive); case IndexFileName: return m_fileName.compare(compareValue.getFileName(), Qt::CaseInsensitive);
case IndexIconPath: return m_iconPath.compare(compareValue.getIconPath(), Qt::CaseInsensitive); case IndexIconPath: return m_iconFile.compare(compareValue.getIconFile(), Qt::CaseInsensitive);
case IndexCG: return m_cg.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getCG()); case IndexCG: return m_cg.comparePropertyByIndex(index.copyFrontRemoved(), compareValue.getCG());
case IndexSupportedParts: return m_supportedParts.compare(compareValue.getSupportedParts()); case IndexSupportedParts: return m_supportedParts.compare(compareValue.getSupportedParts());
case IndexModelTypeAsString: case IndexModelTypeAsString:
@@ -567,10 +567,10 @@ namespace BlackMisc
CPixmap CAircraftModel::loadIcon(CStatusMessage &success) const CPixmap CAircraftModel::loadIcon(CStatusMessage &success) const
{ {
static const CStatusMessage noIcon(this, CStatusMessage::SeverityInfo, u"no icon"); static const CStatusMessage noIcon(this, CStatusMessage::SeverityInfo, u"no icon");
if (m_iconPath.isEmpty()) { success = noIcon; return CPixmap(); } if (m_iconFile.isEmpty()) { success = noIcon; return CPixmap(); }
// load from file // load from file
const CPixmap pm(CPixmap::loadFromFile(m_iconPath, success)); const CPixmap pm(CPixmap::loadFromFile(m_iconFile, success));
return pm; return pm;
} }
@@ -659,6 +659,12 @@ namespace BlackMisc
m_distributor.updateMissingParts(otherModel.getDistributor()); m_distributor.updateMissingParts(otherModel.getDistributor());
} }
void CAircraftModel::updateByExistingDirectories(const CAircraftModel &otherModel)
{
if (otherModel.hasExistingCorrespondingFile()) { this->setFileName(otherModel.getFileName()); }
if (otherModel.hasExistingIconFile()) { this->setIconFile(otherModel.getIconFile()); }
}
bool CAircraftModel::hasQueriedModelString() const bool CAircraftModel::hasQueriedModelString() const
{ {
return m_modelType == TypeQueriedFromNetwork && this->hasModelString(); return m_modelType == TypeQueriedFromNetwork && this->hasModelString();
@@ -710,13 +716,13 @@ namespace BlackMisc
{ {
// other local, priority // other local, priority
this->setFileName(model.getFileName()); this->setFileName(model.getFileName());
this->setIconPath(model.getIconPath()); this->setIconFile(model.getIconFile());
return; return;
} }
// both not local, override empty values // both not local, override empty values
if (m_fileName.isEmpty()) { this->setFileName(model.getFileName()); } if (m_fileName.isEmpty()) { this->setFileName(model.getFileName()); }
if (m_iconPath.isEmpty()) { this->setIconPath(model.getIconPath()); } if (m_iconFile.isEmpty()) { this->setIconFile(model.getIconFile()); }
} }
bool CAircraftModel::adjustLocalFileNames(const QString &newModelDir, const QString &stripModelDirIndicator) bool CAircraftModel::adjustLocalFileNames(const QString &newModelDir, const QString &stripModelDirIndicator)
@@ -760,6 +766,13 @@ namespace BlackMisc
return this->getFileDirectory().absolutePath(); return this->getFileDirectory().absolutePath();
} }
bool CAircraftModel::hasExistingIconFile() const
{
if (m_iconFile.isEmpty()) { return false; }
const QFileInfo fi(m_iconFile);
return fi.exists();
}
bool CAircraftModel::matchesModelString(const QString &modelString, Qt::CaseSensitivity sensitivity) const bool CAircraftModel::matchesModelString(const QString &modelString, Qt::CaseSensitivity sensitivity) const
{ {
return stringCompare(modelString, m_modelString, sensitivity); return stringCompare(modelString, m_modelString, sensitivity);

View File

@@ -366,6 +366,10 @@ namespace BlackMisc
//! Update missing parts from another model //! Update missing parts from another model
void updateMissingParts(const CAircraftModel &otherModel, bool dbModelPriority = true); void updateMissingParts(const CAircraftModel &otherModel, bool dbModelPriority = true);
//! Update the directories from other model
//! \sa updateLocalFileNames
void updateByExistingDirectories(const CAircraftModel &otherModel);
//! Queried model string? //! Queried model string?
bool hasQueriedModelString() const; bool hasQueriedModelString() const;
@@ -450,11 +454,14 @@ namespace BlackMisc
//! File name //! File name
void setFileName(const QString &fileName) { m_fileName = fileName; } void setFileName(const QString &fileName) { m_fileName = fileName; }
//! File representing model //! Icon file representing model
const QString &getIconPath() const { return m_iconPath; } const QString &getIconFile() const { return m_iconFile; }
//! File representing model //! Icon file representing model
void setIconPath(const QString &iconFile) { m_iconPath = iconFile; } void setIconFile(const QString &iconFile) { m_iconFile = iconFile; }
//! Is the icon file existing?
bool hasExistingIconFile() const;
//! Get timestamp //! Get timestamp
QDateTime getFileTimestamp() const; QDateTime getFileTimestamp() const;
@@ -544,7 +551,7 @@ namespace BlackMisc
QString m_name; //!< Model name QString m_name; //!< Model name
QString m_description; //!< descriptive text QString m_description; //!< descriptive text
QString m_fileName; //!< file name QString m_fileName; //!< file name
QString m_iconPath; //!< a file representing the aircraft as icon QString m_iconFile; //!< a file representing the aircraft as icon
QString m_supportedParts; //!< supported parts QString m_supportedParts; //!< supported parts
qint64 m_fileTimestamp = -1; //!< file timestamp of originating file (if applicable) qint64 m_fileTimestamp = -1; //!< file timestamp of originating file (if applicable)
ModelType m_modelType = TypeUnknown; //!< model string is coming representing ...? ModelType m_modelType = TypeUnknown; //!< model string is coming representing ...?
@@ -568,7 +575,7 @@ namespace BlackMisc
BLACK_METAMEMBER(name), BLACK_METAMEMBER(name),
BLACK_METAMEMBER(description, 0, DisabledForComparison), BLACK_METAMEMBER(description, 0, DisabledForComparison),
BLACK_METAMEMBER(fileName, 0, DisabledForComparison), BLACK_METAMEMBER(fileName, 0, DisabledForComparison),
BLACK_METAMEMBER(iconPath, 0, DisabledForComparison), BLACK_METAMEMBER(iconFile, 0, DisabledForComparison),
BLACK_METAMEMBER(fileTimestamp, 0, DisabledForComparison), BLACK_METAMEMBER(fileTimestamp, 0, DisabledForComparison),
BLACK_METAMEMBER(modelType), BLACK_METAMEMBER(modelType),
BLACK_METAMEMBER(modelMode) BLACK_METAMEMBER(modelMode)

View File

@@ -491,14 +491,14 @@ namespace BlackMisc
{ {
if (modelString.isEmpty()) { return {}; } if (modelString.isEmpty()) { return {}; }
const CAircraftModel m(findFirstByModelStringOrDefault(modelString, Qt::CaseInsensitive)); const CAircraftModel m(findFirstByModelStringOrDefault(modelString, Qt::CaseInsensitive));
return m.getIconPath(); return m.getIconFile();
} }
QString CAircraftModelList::findModelIconPathByCallsign(const CCallsign &callsign) const QString CAircraftModelList::findModelIconPathByCallsign(const CCallsign &callsign) const
{ {
if (callsign.isEmpty()) { return {}; } if (callsign.isEmpty()) { return {}; }
const CAircraftModel m(findFirstByCallsignOrDefault(callsign)); const CAircraftModel m(findFirstByCallsignOrDefault(callsign));
return m.getIconPath(); return m.getIconFile();
} }
CAircraftModelList CAircraftModelList::findModelsWithoutExistingFile() const CAircraftModelList CAircraftModelList::findModelsWithoutExistingFile() const

View File

@@ -133,7 +133,7 @@ namespace BlackMisc
model.setName(this->getSimName()); model.setName(this->getSimName());
model.setMSecsSinceEpoch(m_timestampMSecsSinceEpoch); // aircraft.cfg file timestamp model.setMSecsSinceEpoch(m_timestampMSecsSinceEpoch); // aircraft.cfg file timestamp
model.setFileTimestamp(m_timestampMSecsSinceEpoch); model.setFileTimestamp(m_timestampMSecsSinceEpoch);
model.setIconPath(this->getThumbnailFileNameChecked()); model.setIconFile(this->getThumbnailFileNameChecked());
const QString designator(CAircraftIcaoCode::normalizeDesignator(this->getAtcModel())); const QString designator(CAircraftIcaoCode::normalizeDesignator(this->getAtcModel()));
CAircraftIcaoCode aircraft( CAircraftIcaoCode aircraft(

View File

@@ -381,7 +381,7 @@ namespace BlackMisc
QString getNetworkModelLiveryDifference() const; QString getNetworkModelLiveryDifference() const;
//! \copydoc BlackMisc::Simulation::CAircraftModel::getIconPath //! \copydoc BlackMisc::Simulation::CAircraftModel::getIconPath
const QString &getIconPath() const { return m_models[CurrentModel].getIconPath(); } const QString &getIconFile() const { return m_models[CurrentModel].getIconFile(); }
//! Get model string //! Get model string
const QString &getModelString() const { return m_models[CurrentModel].getModelString(); } const QString &getModelString() const { return m_models[CurrentModel].getModelString(); }