Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
@@ -0,0 +1,790 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Importieren von SAAB-Dateien
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "saab_import.h"
|
||||
#include "ui_saab_import.h"
|
||||
#include "saab_logging.h"
|
||||
#include "saab_import_show.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
|
||||
#include <ngltools/ngltools_filesystem.h>
|
||||
#include <Common/participant_dis_helper.h>
|
||||
#include <Plugins/ParticipantManagement/ppm_data_plugin_interface.h>
|
||||
#include <LtsSession/lts_session.h>
|
||||
#include <LtsUtilsSettings/settings.h>
|
||||
#include <LtsWidgets/lts_message_dialog.h>
|
||||
#include "saab_mapping_dialog.h"
|
||||
|
||||
namespace saab
|
||||
{
|
||||
|
||||
ImportSaab::ImportSaab(ParticipantManagement::ParticipantEditModel *pModel, const QModelIndex &index, QWidget *parent, LtsSession::LtsSession *pSession)
|
||||
: NGLDialog(parent)
|
||||
, m_xmlFile(nullptr)
|
||||
, m_configFile(nullptr)
|
||||
, m_indexRoot(index)
|
||||
, m_pModel(pModel)
|
||||
, m_requestHelper(new LtsUtils::RequestHelper(this))
|
||||
, m_pUi(new Ui_SAABImport)
|
||||
, m_logger(saab::getLogger("ImportSaab"))
|
||||
{
|
||||
m_pUi->setupUi(this);
|
||||
setWindowTitle(tr("Import SAAB Orbat"));
|
||||
|
||||
if (!pSession->getDtc<ParticipantManagement::DataInterface>(m_ppmDtc) || !pSession->getFtc<ParticipantManagement::DataInterface>(m_ppmFtc))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Fetching m_ppmDtc or m_ppmFtc failed!";
|
||||
setEnabled(false);
|
||||
}
|
||||
else
|
||||
m_mapTypes = m_ppmDtc->types();
|
||||
|
||||
connect(m_pUi->m_pushbutton_SelectFile, &QToolButton::clicked,
|
||||
this, &ImportSaab::slotOpenImportDialog);
|
||||
connect(m_pUi->m_pushbutton_SelectConfig, &QToolButton::clicked,
|
||||
this, &ImportSaab::slotOpenConfigDialog);
|
||||
connect(m_pUi->m_pushButton_StartImport, &QPushButton::clicked,
|
||||
this, &ImportSaab::slotStartImport);
|
||||
|
||||
QString strImportFile = LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("SAAB"), QStringLiteral("pathSelectedImportFile"), QString()).toString();
|
||||
QString strConfigFile = LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("SAAB"), QStringLiteral("pathSelectedConfigFile"), QString()).toString();
|
||||
|
||||
m_pUi->m_lineedit_ImportFile->setText(strImportFile);
|
||||
m_pUi->m_lineedit_configFile->setText(strConfigFile);
|
||||
|
||||
m_pUi->m_pushButton_StartImport->setEnabled(strImportFile.size() && strConfigFile.size());
|
||||
}
|
||||
|
||||
|
||||
ImportSaab::~ImportSaab()
|
||||
{
|
||||
delete m_pUi;
|
||||
}
|
||||
|
||||
|
||||
void ImportSaab::slotOpenImportDialog()
|
||||
{
|
||||
QString strPathSelectedImportFolder = LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("SAAB"), QStringLiteral("pathSelectedImportFolder"), QStringLiteral("/shd/CTC/TOOLS/TDS/")).toString();
|
||||
QString strPathSelectedImportFile = LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("SAAB"), QStringLiteral("pathSelectedImportFile"), QStringLiteral("/shd/CTC/TOOLS/TDS/")).toString();
|
||||
|
||||
QList<QUrl> urls;
|
||||
urls << QUrl::fromLocalFile(strPathSelectedImportFile);
|
||||
|
||||
QFileDialog fileDialog(this, tr("Select File"), strPathSelectedImportFolder, tr("XML files (*.xml)"));
|
||||
fileDialog.setSidebarUrls(urls);
|
||||
fileDialog.setOptions(QFileDialog::ReadOnly);
|
||||
fileDialog.setFileMode(QFileDialog::ExistingFile);
|
||||
|
||||
if (fileDialog.exec()) // TODO: use show(), use signals & slots !
|
||||
{
|
||||
strPathSelectedImportFile = fileDialog.selectedFiles().constFirst();
|
||||
LtsUtils::OperatorSettings::getInstance()->setValue(QStringLiteral("SAAB"), QStringLiteral("pathSelectedImportFolder"), strPathSelectedImportFolder);
|
||||
|
||||
if (!strPathSelectedImportFile.size())
|
||||
return;
|
||||
|
||||
LtsUtils::OperatorSettings::getInstance()->setValue(QStringLiteral("SAAB"), QStringLiteral("pathSelectedImportFile"), strPathSelectedImportFile);
|
||||
m_pUi->m_lineedit_ImportFile->setText(strPathSelectedImportFile);
|
||||
m_pUi->m_pushButton_StartImport->setEnabled(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("SAAB"), QStringLiteral("pathSelectedConfigFile"), QString()).toString().size());
|
||||
}
|
||||
}
|
||||
|
||||
void ImportSaab::slotOpenConfigDialog()
|
||||
{
|
||||
QString strPathSelectedConfigFolder = LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("SAAB"), QStringLiteral("pathSelectedConfigFolder"), QStringLiteral("/shd/CTC/TOOLS/TDS/")).toString();
|
||||
QString strPathSelectedConfigFile = LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("SAAB"), QStringLiteral("pathSelectedConfigFile"), QStringLiteral("/shd/CTC/TOOLS/TDS/")).toString();
|
||||
|
||||
QList<QUrl> urls;
|
||||
urls << QUrl::fromLocalFile(strPathSelectedConfigFile);
|
||||
|
||||
QFileDialog fileDialog(this, tr("Select File"), strPathSelectedConfigFolder, tr("XML files (*.xml)"));
|
||||
fileDialog.setSidebarUrls(urls);
|
||||
fileDialog.setOptions(QFileDialog::ReadOnly);
|
||||
fileDialog.setFileMode(QFileDialog::ExistingFile);
|
||||
|
||||
if (fileDialog.exec()) // TODO: use show(), use signals & slots !
|
||||
{
|
||||
strPathSelectedConfigFile = fileDialog.selectedFiles().constFirst();
|
||||
LtsUtils::OperatorSettings::getInstance()->setValue(QStringLiteral("SAAB"), QStringLiteral("pathSelectedConfigFolder"), strPathSelectedConfigFolder);
|
||||
|
||||
if (!strPathSelectedConfigFile.size())
|
||||
return;
|
||||
|
||||
LtsUtils::OperatorSettings::getInstance()->setValue(QStringLiteral("SAAB"), QStringLiteral("pathSelectedConfigFile"), strPathSelectedConfigFile);
|
||||
m_pUi->m_lineedit_configFile->setText(strPathSelectedConfigFile);
|
||||
m_pUi->m_pushButton_StartImport->setEnabled(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("SAAB"), QStringLiteral("pathSelectedImportFile"), QString()).toString().size());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ImportSaab::slotStartImport()
|
||||
{
|
||||
if (m_xmlFile)
|
||||
{
|
||||
m_xmlFile->close();
|
||||
delete m_xmlFile;
|
||||
m_xmlFile = nullptr;
|
||||
}
|
||||
|
||||
if (m_configFile)
|
||||
{
|
||||
m_configFile->close();
|
||||
delete m_configFile;
|
||||
m_configFile = nullptr;
|
||||
}
|
||||
|
||||
m_pModel->resetModel();
|
||||
|
||||
QString fileName = m_pUi->m_lineedit_ImportFile->text();
|
||||
QString configFileName = m_pUi->m_lineedit_configFile->text();
|
||||
|
||||
m_xmlFile = new QFile(fileName, this);
|
||||
m_configFile = new QFile(configFileName, this);
|
||||
|
||||
if (!isValidSaabOrbatFile())
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Error while reading file \"%1\".").arg(fileName));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isValidConfigFile())
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Error while reading file \"%1\".").arg(configFileName));
|
||||
return;
|
||||
}
|
||||
|
||||
importExerciseScenario();
|
||||
}
|
||||
|
||||
ParticipantManagement::ParticipantData ImportSaab::createParticipant(SaabPlayer *player)
|
||||
{
|
||||
ParticipantManagement::ParticipantData p;
|
||||
|
||||
// Note: According to Uli D., in GÜZ, TactId shall be static and
|
||||
// received from SAAB and designator shall be freely changeable.
|
||||
|
||||
// Designator
|
||||
p.tacticalIdentifier(player->designation.toStdString());
|
||||
|
||||
// State and Equipment
|
||||
p.equipmentNumber(player->simulatorId != INT_MIN ? player->simulatorId : 0);
|
||||
p.assignState() = ParticipantManagement::ParticipantAssignState::HandoutExcon;
|
||||
|
||||
if (player->simulatorId != INT_MIN)
|
||||
p.externalId(player->simulatorId);
|
||||
|
||||
p.symbol(m_mapTypes[player->mappedTypeId].symbol());
|
||||
p.typeId(player->mappedTypeId); // Class type is internally derived from typeid, no need (and possibility) to set it here
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void ImportSaab::insertParticipant(SaabPlayer *player, const QModelIndex &index)
|
||||
{
|
||||
ParticipantManagement::ParticipantData newParticipant = createParticipant(player);
|
||||
createNode(newParticipant, index, player);
|
||||
}
|
||||
|
||||
// Parties are the root units (m_rootUnits)
|
||||
void ImportSaab::insertParty(SaabUnit *party)
|
||||
{
|
||||
// Create "Force"-Node -> No symbol, no tact. identifier, no classtype
|
||||
ParticipantManagement::ParticipantData newParty;
|
||||
newParty.designator(party->designation.toStdString());
|
||||
createNode(newParty, m_indexRoot, party);
|
||||
}
|
||||
|
||||
|
||||
void ImportSaab::createNode(const ParticipantManagement::ParticipantData &participant, const QModelIndex &index, SaabPlayer *parent)
|
||||
{
|
||||
int newRow = m_pModel->onInsertRow(index, participant);
|
||||
QModelIndex newIdx = m_pModel->index(newRow, 0, index);
|
||||
m_parentIndexCache[parent] = newIdx;
|
||||
}
|
||||
|
||||
SaabPerson ImportSaab::saabPersonByGUID(const QString &guid) const
|
||||
{
|
||||
for (const auto ¤t : qAsConst(m_saabPersons))
|
||||
{
|
||||
if (current.guid == guid)
|
||||
return current;
|
||||
}
|
||||
|
||||
return SaabPerson();
|
||||
}
|
||||
|
||||
SaabVehicle ImportSaab::saabVehicleByGUID(const QString &guid) const
|
||||
{
|
||||
for (const auto ¤t : qAsConst(m_saabVehicles))
|
||||
{
|
||||
if (current.guid == guid)
|
||||
return current;
|
||||
}
|
||||
|
||||
return SaabVehicle();
|
||||
}
|
||||
|
||||
void ImportSaab::importOrbat()
|
||||
{
|
||||
if (!m_xmlFile)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Not possible to import ORBAT: No file selected";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_xmlFile->open(QIODevice::ReadOnly))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Not possible to import ORBAT: Could not open file \""
|
||||
<< m_xmlFile->fileName()
|
||||
<< "\" for reading.";
|
||||
return;
|
||||
}
|
||||
|
||||
QXmlStreamReader reader(m_xmlFile);
|
||||
|
||||
qDeleteAll(m_rootUnits);
|
||||
m_rootUnits.clear();
|
||||
m_unknownTypes.clear();
|
||||
|
||||
while (!(reader.readNext() == QXmlStreamReader::EndElement && reader.name() == XmlStrings::SAAB_ORBAT()))
|
||||
{
|
||||
if (reader.atEnd())
|
||||
break;
|
||||
|
||||
if (reader.tokenType() == QXmlStreamReader::StartElement && reader.name() == XmlStrings::SAAB_UNIT())
|
||||
{
|
||||
SaabUnit *unit = static_cast<SaabUnit *>(readUnit(&reader));
|
||||
|
||||
if (unit->isDeletedByDefault)
|
||||
continue;
|
||||
|
||||
m_rootUnits.append(unit);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_logger.isDebugEnabled())
|
||||
{
|
||||
for (SaabUnit *u : qAsConst(m_rootUnits))
|
||||
DEBUG_LOG(m_logger) << u->toString();
|
||||
}
|
||||
|
||||
m_xmlFile->close();
|
||||
}
|
||||
|
||||
void ImportSaab::importConfig()
|
||||
{
|
||||
if (!m_mapSymbols.isEmpty() || !m_mapEchelons.isEmpty())
|
||||
{
|
||||
using namespace LtsWidgets;
|
||||
|
||||
Button b = LtsMessageDialog::showMessage(this,
|
||||
tr("A config is already imported. Overwrite?"),
|
||||
tr("Overwrite config?"),
|
||||
Behaviour::Modal,
|
||||
Button::Yes | Button::No);
|
||||
if (b != Button::Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_configFile)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Not possible to read config: No file selected";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_configFile->open(QIODevice::ReadOnly))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Not possible to read config: Could not open file \""
|
||||
<< m_configFile->fileName()
|
||||
<< "\" for reading.";
|
||||
return;
|
||||
}
|
||||
|
||||
m_mapSymbols.clear();
|
||||
m_mapEchelons.clear();
|
||||
m_mapSaabSymbolToType.clear();
|
||||
|
||||
QXmlStreamReader reader(m_configFile);
|
||||
|
||||
using namespace XmlStrings;
|
||||
|
||||
while (!reader.atEnd())
|
||||
{
|
||||
if (reader.readNextStartElement())
|
||||
{
|
||||
if (reader.name() == SAAB_SYMBOL())
|
||||
{
|
||||
SaabSymbol newSymbol = readSymbol(&reader);
|
||||
m_mapSymbols.insert(newSymbol.code, newSymbol);
|
||||
}
|
||||
else if (reader.name() == SAAB_ECHELON())
|
||||
{
|
||||
SaabEchelon newEchelon = readEchelon(&reader);
|
||||
m_mapEchelons.insert(newEchelon.code, newEchelon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
m_configFile->close();
|
||||
}
|
||||
|
||||
QVector<SaabPlayer *> ImportSaab::flattenedPlayersWithoutRootUnits() const
|
||||
{
|
||||
QVector<SaabPlayer *> result;
|
||||
|
||||
for (SaabUnit *p : qAsConst(m_rootUnits))
|
||||
{
|
||||
QVector<SaabPlayer *> inferiorInferiors = inferiors(p);
|
||||
|
||||
for (SaabPlayer *infInf : qAsConst(inferiorInferiors))
|
||||
result.append(infInf);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QVector<SaabPlayer *> ImportSaab::inferiors(SaabPlayer *player) const
|
||||
{
|
||||
QVector<SaabPlayer *> result;
|
||||
|
||||
if (typeid(*player) != typeid(SaabUnit))
|
||||
{
|
||||
result.append(player);
|
||||
return result;
|
||||
}
|
||||
|
||||
SaabUnit *unit = static_cast<SaabUnit *>(player);
|
||||
|
||||
if (!m_rootUnits.contains(unit))
|
||||
result.append(player);
|
||||
|
||||
for (SaabPlayer *inf : qAsConst(unit->inferiors))
|
||||
{
|
||||
QVector<SaabPlayer *> inferiorInferiors = inferiors(inf);
|
||||
for (SaabPlayer *infInf : qAsConst(inferiorInferiors))
|
||||
result.append(infInf);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SaabPlayer *ImportSaab::readUnit(QXmlStreamReader *reader) const
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "reading unit: tokentype: " << reader->tokenString() << " | name: " << reader->name().toString();
|
||||
|
||||
SaabUnit *result = new SaabUnit;
|
||||
|
||||
using namespace XmlStrings;
|
||||
|
||||
QMap<QString, SaabPlayer*(ImportSaab::*)(QXmlStreamReader *)const> funcMap;
|
||||
funcMap.insert(SAAB_PERSON_PLAYER(), &ImportSaab::readPersonPlayer);
|
||||
funcMap.insert(SAAB_OC_PLAYER(), &ImportSaab::readOcPlayer);
|
||||
funcMap.insert(SAAB_VEHICLE_PLAYER(), &ImportSaab::readVehiclePlayer);
|
||||
funcMap.insert(SAAB_UNIT(), &ImportSaab::readUnit);
|
||||
|
||||
result->guid = reader->attributes().value(SAAB_ID()).toString();
|
||||
|
||||
while (!(reader->readNext() == QXmlStreamReader::EndElement && reader->name() == SAAB_UNIT()))
|
||||
{
|
||||
if (reader->tokenType() == QXmlStreamReader::StartElement)
|
||||
{
|
||||
if (reader->name() == SAAB_DESIGNATION())
|
||||
result->designation = reader->readElementText();
|
||||
else if (reader->name() == SAAB_FORCE())
|
||||
result->force = reader->readElementText();
|
||||
else if (reader->name() == SAAB_SYMBOL())
|
||||
result->symbol = reader->readElementText();
|
||||
else if (reader->name() == SAAB_TRASHCAN())
|
||||
result->trashcan = reader->readElementText() == SAAB_TRUE();
|
||||
else if (reader->name() == SAAB_POSITION_BY_PLAYER_ID())
|
||||
result->positionByPlayerId = reader->readElementText();
|
||||
else if (reader->name() == SAAB_UNIT_SIZE())
|
||||
result->unitSize = reader->readElementText();
|
||||
else if (reader->name() == SAAB_CHANGE_INFO())
|
||||
result->isDeletedByDefault = reader->attributes().value(SAAB_CHANGE_TYPE()).toString() == SAAB_DELETE();
|
||||
else if (reader->name() == SAAB_ORBAT_ENTITIES())
|
||||
{
|
||||
while (!(reader->readNext() == QXmlStreamReader::EndElement && reader->name() == SAAB_ORBAT_ENTITIES()))
|
||||
{
|
||||
QString tagName = reader->name().toString();
|
||||
if (reader->tokenType() == QXmlStreamReader::StartElement && funcMap.contains(tagName))
|
||||
{
|
||||
SaabPlayer *newParticipant = (this->*funcMap.value(tagName))(reader);
|
||||
|
||||
if (newParticipant->isDeletedByDefault || newParticipant->isExternalPlayer)
|
||||
continue;
|
||||
|
||||
newParticipant->superior = result;
|
||||
result->inferiors.append(newParticipant);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if the unit has to take the position of a specific participant,
|
||||
// take the participant to the top of the inferiors
|
||||
if (!result->positionByPlayerId.isEmpty())
|
||||
{
|
||||
int index = playerIndexByGuid(result->guid, result->inferiors);
|
||||
|
||||
if (index < 0)
|
||||
WARNING_LOG(m_logger) << SAAB_POSITION_BY_PLAYER_ID() << " set, but GUID " << result->positionByPlayerId << " could not be found.";
|
||||
else
|
||||
result->inferiors.prepend(result->inferiors.takeAt(index));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SaabPlayer *ImportSaab::readOcPlayer(QXmlStreamReader *reader) const
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "reading oc player: tokentype: " << reader->tokenString() << " | name: " << reader->name().toString();
|
||||
|
||||
return readPersonOcPlayer<SaabOcPlayer>(reader, XmlStrings::SAAB_OC_PLAYER());;
|
||||
}
|
||||
|
||||
SaabPlayer *ImportSaab::readPersonPlayer(QXmlStreamReader *reader) const
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "reading person player: tokentype: " << reader->tokenString() << " | name: " << reader->name().toString();
|
||||
|
||||
return readPersonOcPlayer<SaabPersonPlayer>(reader, XmlStrings::SAAB_PERSON_PLAYER());
|
||||
}
|
||||
|
||||
SaabPlayer *ImportSaab::readVehiclePlayer(QXmlStreamReader *reader) const
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "reading vehicle player: tokentype: " << reader->tokenString() << " | name: " << reader->name().toString();
|
||||
|
||||
using namespace XmlStrings;
|
||||
|
||||
SaabVehiclePlayer *result = readPlayerBaseData<SaabVehiclePlayer>(reader, SAAB_VEHICLE_PLAYER(), SAAB_VEHICLE_REF_ID());
|
||||
|
||||
if (!result->refId.isEmpty())
|
||||
{
|
||||
SaabVehicle vehicle = saabVehicleByGUID(reader->readElementText());
|
||||
|
||||
if (vehicle.guid.isEmpty())
|
||||
WARNING_LOG(m_logger) << SAAB_VEHICLE_REF_ID() << " set, but GUID " << result->refId << " could not be found.";
|
||||
else
|
||||
{
|
||||
result->registrationNumber = vehicle.registrationNumber;
|
||||
result->description = vehicle.description;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SaabSymbol ImportSaab::readSymbol(QXmlStreamReader *reader) const
|
||||
{
|
||||
SaabSymbol result;
|
||||
|
||||
using namespace XmlStrings;
|
||||
|
||||
while (reader->readNext() != QXmlStreamReader::EndElement && reader->name() != SAAB_SYMBOL())
|
||||
{
|
||||
if (reader->name() == SAAB_CODE())
|
||||
result.code = reader->readElementText();
|
||||
else if (reader->name() == SAAB_TEXT())
|
||||
result.text = reader->readElementText();
|
||||
else if (reader->name() == SAAB_SYMBOL_ID())
|
||||
result.symbolId = reader->readElementText();
|
||||
else if (reader->name() == SAAB_MODEL_ID())
|
||||
result.modelId = reader->readElementText();
|
||||
else if (reader->name() == SAAB_ECHELON_ID())
|
||||
result.echelonId = reader->readElementText();
|
||||
else if (reader->name() == SAAB_PLAYER_TYPE_ID())
|
||||
result.playerTypeId = reader->readElementText();
|
||||
else if (reader->name() == SAAB_COLOR())
|
||||
result.color = reader->readElementText();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SaabEchelon ImportSaab::readEchelon(QXmlStreamReader *reader) const
|
||||
{
|
||||
SaabEchelon result;
|
||||
|
||||
using namespace XmlStrings;
|
||||
|
||||
while (reader->readNext() != QXmlStreamReader::EndElement && reader->name() != SAAB_ECHELON())
|
||||
{
|
||||
if (reader->name() == SAAB_CODE())
|
||||
result.code = reader->readElementText();
|
||||
else if (reader->name() == SAAB_TEXT())
|
||||
result.text = reader->readElementText();
|
||||
else if (reader->name() == SAAB_ID())
|
||||
result.id = reader->readElementText();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ImportSaab::playerIndexByGuid(const QString &guid, const QVector<SaabPlayer *> &vec)
|
||||
{
|
||||
for (int i = 0; i < vec.size(); ++i)
|
||||
{
|
||||
if (vec.at(i)->guid == guid)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ImportSaab::importExerciseScenario()
|
||||
{
|
||||
using namespace XmlStrings;
|
||||
|
||||
importConfig();
|
||||
importRefData(m_saabPersons, SAAB_PERSONS(), SAAB_PERSON(), SAAB_PERSONAL_ID(), SAAB_NAME()); // import persons
|
||||
importRefData(m_saabVehicles, SAAB_VEHICLES(), SAAB_VEHICLE(), SAAB_REGISTRATION_NUMBER(), SAAB_DESCRIPTION()); // import vehicles
|
||||
importOrbat();
|
||||
|
||||
for (SaabUnit *party : qAsConst(m_rootUnits))
|
||||
insertParty(party);
|
||||
|
||||
QVector<SaabPlayer *> vecUnitsWithValidDISTypes = resolveImportMapping(flattenedPlayersWithoutRootUnits());
|
||||
|
||||
if (!vecUnitsWithValidDISTypes.size())
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("There are no units or participants which can be imported."), tr("Import Warning"));
|
||||
return;
|
||||
}
|
||||
|
||||
buildImportTreeView(vecUnitsWithValidDISTypes);
|
||||
|
||||
close();
|
||||
}
|
||||
|
||||
void ImportSaab::buildImportTreeView(const QVector<SaabPlayer *> &vecUnitsWithValidDISTypes)
|
||||
{
|
||||
QVector<SaabPlayer *> tmp;
|
||||
QVector<SaabPlayer *> current = vecUnitsWithValidDISTypes;
|
||||
do
|
||||
{
|
||||
for (SaabPlayer *player : current)
|
||||
{
|
||||
auto it = m_parentIndexCache.find(player->superior);
|
||||
|
||||
if (it == m_parentIndexCache.end())
|
||||
{
|
||||
// check if the parent exists in vecUnitsWithValidDISTypes for the next approach
|
||||
if (vecUnitsWithValidDISTypes.contains(player->superior))
|
||||
tmp.append(player);
|
||||
else
|
||||
WARNING_LOG(m_logger) << "Parent missing: Could not import player " << player->designation;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
QModelIndex &parentIdx = (*it);
|
||||
insertParticipant(player, parentIdx);
|
||||
}
|
||||
|
||||
current = tmp;
|
||||
tmp.clear();
|
||||
} while (!current.isEmpty());
|
||||
}
|
||||
|
||||
bool ImportSaab::isValidSaabOrbatFile() const
|
||||
{
|
||||
if (!m_xmlFile)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Not possible to import ORBAT: No file selected";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_xmlFile->open(QIODevice::ReadOnly))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Not possible to import ORBAT: Could not open file \""
|
||||
<< m_xmlFile->fileName()
|
||||
<< "\" for reading.";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool hasExerciseOrbatRoot = false;
|
||||
bool hasExercise = false;
|
||||
bool hasOrbat = false;
|
||||
|
||||
QXmlStreamReader reader(m_xmlFile);
|
||||
|
||||
using namespace XmlStrings;
|
||||
|
||||
while (!(hasExerciseOrbatRoot && hasExercise && hasOrbat) && !reader.atEnd())
|
||||
{
|
||||
if (reader.readNextStartElement())
|
||||
{
|
||||
if (reader.name() == SAAB_EXERCISE_ORBAT())
|
||||
hasExerciseOrbatRoot = true;
|
||||
else if (reader.name() == SAAB_EXERCISE())
|
||||
hasExercise = true;
|
||||
else if (reader.name() == SAAB_ORBAT())
|
||||
hasOrbat = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_xmlFile->close();
|
||||
|
||||
if (!hasExerciseOrbatRoot)
|
||||
ERROR_LOG(m_logger) << "Could not find " << SAAB_EXERCISE_ORBAT() << " in file \"" << m_xmlFile->fileName() << '\"';
|
||||
if (!hasExercise)
|
||||
ERROR_LOG(m_logger) << "Could not find " << SAAB_EXERCISE() << " in file \"" << m_xmlFile->fileName() << '\"';
|
||||
if (!hasOrbat)
|
||||
ERROR_LOG(m_logger) << "Could not find " << SAAB_ORBAT() << " in file \"" << m_xmlFile->fileName() << '\"';
|
||||
|
||||
return hasExerciseOrbatRoot && hasExercise && hasOrbat;
|
||||
}
|
||||
|
||||
bool ImportSaab::isValidConfigFile() const
|
||||
{
|
||||
if (!m_configFile)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Not possible to read config: No file selected";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_configFile->open(QIODevice::ReadOnly))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Not possible to read config: Could not open file \""
|
||||
<< m_configFile->fileName()
|
||||
<< "\" for reading.";
|
||||
return false;
|
||||
}
|
||||
|
||||
using namespace XmlStrings;
|
||||
|
||||
QXmlStreamReader reader(m_configFile);
|
||||
|
||||
bool hasSymbols = false;
|
||||
bool hasEchelons = false;
|
||||
|
||||
while (!reader.atEnd() && !(hasSymbols && hasEchelons))
|
||||
{
|
||||
if (reader.readNextStartElement())
|
||||
{
|
||||
if (reader.name() == SAAB_SYMBOLS())
|
||||
hasSymbols = true;
|
||||
else if (reader.name() == SAAB_ECHELONS())
|
||||
hasEchelons = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_configFile->close();
|
||||
|
||||
if (!hasEchelons)
|
||||
ERROR_LOG(m_logger) << "Could not find " << SAAB_ECHELONS() << " in file \"" << m_configFile->fileName() << '\"';
|
||||
if (!hasSymbols)
|
||||
ERROR_LOG(m_logger) << "Could not find " << SAAB_SYMBOLS() << " in file \"" << m_configFile->fileName() << '\"';
|
||||
|
||||
return hasEchelons && hasSymbols;
|
||||
}
|
||||
|
||||
bool ImportSaab::hasValidType(SaabPlayer *player) const
|
||||
{
|
||||
return m_mapSymbols.value(player->symbol).mappedTypeId > -1;
|
||||
}
|
||||
|
||||
QVector<SaabPlayer *> ImportSaab::resolveImportMapping(const QVector<SaabPlayer *> &playerVec)
|
||||
{
|
||||
QVector<SaabPlayer *> vecObjectsWithValidTypes;
|
||||
QMap<QString, QVector<SaabPlayer *>> mapParticipantsWithUnknownType, mapUnitsWithUnknownType;
|
||||
|
||||
// first perform a mapping of saab type to rme type
|
||||
for (SaabPlayer *player : playerVec)
|
||||
{
|
||||
if (!hasValidType(player))
|
||||
{
|
||||
if (typeid(*player) == typeid(SaabUnit))
|
||||
{
|
||||
QString text = m_mapSymbols.contains(player->symbol) ? m_mapSymbols.value(player->symbol).text : player->symbol;
|
||||
QString unitSize = static_cast<SaabUnit *>(player)->unitSize;
|
||||
text.append(tr(" - Size: %1").arg(m_mapEchelons.contains(unitSize) ? m_mapEchelons.value(unitSize).text : unitSize));
|
||||
mapUnitsWithUnknownType[text].append(player);
|
||||
}
|
||||
else
|
||||
mapParticipantsWithUnknownType[m_mapSymbols.contains(player->symbol) ? m_mapSymbols.value(player->symbol).text : player->symbol].append(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
// A match between the imported unit (its DIS id) and one of the database types exists: Perform mapping, everything is fine.
|
||||
vecObjectsWithValidTypes.append(player);
|
||||
}
|
||||
}
|
||||
|
||||
if (mapUnitsWithUnknownType.size())
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("<b>Units</b> exist whose external type is unknown.<br/>You have to solve this by manually mapping<br/> the external types to existing <b>unit types</b>."), tr("Import Error"));
|
||||
vecObjectsWithValidTypes.append(showMappingDialog(mapUnitsWithUnknownType, true));
|
||||
}
|
||||
|
||||
if (mapParticipantsWithUnknownType.size())
|
||||
{
|
||||
LtsWidgets::LtsMessageDialog::showMessage(this, tr("<b>Participants</b> exist whose external type is unknown.<br/>You have to solve this by manually mapping<br/> the external types to existing <b>participant types</b>."), tr("Import Error"));
|
||||
vecObjectsWithValidTypes.append(showMappingDialog(mapParticipantsWithUnknownType, false));
|
||||
}
|
||||
|
||||
return vecObjectsWithValidTypes;
|
||||
}
|
||||
|
||||
|
||||
QVector<SaabPlayer *> ImportSaab::showMappingDialog(const QMap<QString, QVector<SaabPlayer *>> &mapConflictMap, bool typeClassIsUnit)
|
||||
{
|
||||
QVector<SaabPlayer *> vecUnitsWithValidSymbols;
|
||||
|
||||
int32_t mappedTypeId = 0;
|
||||
|
||||
for (auto it = mapConflictMap.begin(); it != mapConflictMap.end(); ++it)
|
||||
{
|
||||
const QString &strSaabSymbol = it.key();
|
||||
const QVector<SaabPlayer *> &vecData = it.value();
|
||||
|
||||
QString strReason;
|
||||
bool offerDatabaseEntriesWithoutDISType;
|
||||
|
||||
if (!strSaabSymbol.size())
|
||||
{
|
||||
strReason = QString(tr("No type specified."));
|
||||
// Imported unit/participant has no DIS type. Mapping "no DIS type" to database elements without a DIS type does not make sense
|
||||
offerDatabaseEntriesWithoutDISType = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
strReason = QString(tr("Specified type \"%1\" is unknown.")).arg(strSaabSymbol);
|
||||
offerDatabaseEntriesWithoutDISType = true;
|
||||
}
|
||||
|
||||
QString strType = typeClassIsUnit ? tr("unit(s)") : tr("participant(s)");
|
||||
strReason += tr("<br/>This applies for %1 %2. Please choose an option:").arg(QString::number(vecData.size()), strType);
|
||||
|
||||
saab::MappingDialog dialog(this, typeClassIsUnit, strReason, m_ppmDtc, offerDatabaseEntriesWithoutDISType);
|
||||
dialog.exec(); // TODO: use show(), use signals & slots !
|
||||
|
||||
if (dialog.skipAllUnmappedElements())
|
||||
break;
|
||||
|
||||
mappedTypeId = dialog.getMappedTypeId();
|
||||
|
||||
if (dialog.mappingApplied())
|
||||
{
|
||||
m_mapSaabSymbolToType.insert(strSaabSymbol, mappedTypeId);
|
||||
|
||||
for (SaabPlayer *participant : qAsConst(vecData))
|
||||
{
|
||||
participant->mappedTypeId = mappedTypeId;
|
||||
vecUnitsWithValidSymbols.push_back(participant);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vecUnitsWithValidSymbols;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user