Close ppm.msdl/ppm.saab floors: re-implement MSDL/SAAB import without Qt XmlPatterns

Qt6::Xml (QDomDocument) + xmllint schema check; MSDL links XercesC + xsdc++ tree classes; both moved into GROUP12
This commit is contained in:
berrux-dev committed 2026-10-24 19:31:04 +02:00
1 parent 3924b1e72b
commit 8e9594d25c
18 files changed
+179 -248

No files matched your search

+12 -18
View File
@@ -210,8 +210,12 @@ OPTION(BUILD_PLUGINS_PLANEDITOR "Build PlanEditor plugin (requires Qt6 WebEngine
OPTION(BUILD_PLUGINS_ONLINEHELP "Build OnlineHelp plugin (requires Qt6 WebEngine)" OFF)
OPTION(BUILD_PLUGINS_SERVICEMONITOR "Build ServiceMonitor plugin (requires Qt6 WebEngine)" OFF)
OPTION(BUILD_PLUGINS_PARTICIPANT_ORG_CHART "Build ParticipantOrgChart (requires Qt6 WebEngine)" OFF)
OPTION(BUILD_PLUGINS_MSDL "Build MSDL module (requires Qt6 XmlPatterns)" OFF)
OPTION(BUILD_PLUGINS_SAAB "Build Saab module (requires Qt6 XmlPatterns)" OFF)
# MSDL/Saab no longer require Qt XmlPatterns (removed in Qt 6.0): their import
# code was re-implemented with Qt6::Xml (QDomDocument) for the schema check plus
# the external xmllint step for real XSD validation; MSDL additionally links
# XercesC + uses xsdc++-generated tree classes (needs libxerces-c-dev + xsdcxx).
OPTION(BUILD_PLUGINS_MSDL "Build MSDL module (needs XercesC + xsdc++)" OFF)
OPTION(BUILD_PLUGINS_SAAB "Build Saab module (Qt6::Xml only)" OFF)
OPTION(BUILD_RTI "Build RTI Connext DDS dependent modules" OFF)
OPTION(BUILD_VIEWER_ONLY "Build only Viewer module (no RTI required)" OFF)
# Add Lts/ include path globally for QosProfile and other Lts headers
@@ -360,22 +364,12 @@ if(NOT Qt6_FOUND)
message(STATUS "Found Qt6 (minimal): ${Qt6Core_VERSION}")
endif()
# Qt6::XmlPatterns (consumed by the MSDL/Saab import libs, gated by
# BUILD_PLUGINS_MSDL / BUILD_PLUGINS_SAAB): the XmlPatterns module (its own
# qtxmlpatterns repo) was removed in Qt 6.0 and never re-introduced, so no Qt 6
# install carries it. It is NOT part of the component lists above (a missing
# component there would flip Qt6_FOUND off and disable the whole GUI path).
# Find it separately; when absent the two plugins must stay disabled - their
# CMakeLists reference Qt6::XmlPatterns in link libraries and CMake errors at
# generate time for an undefined namespaced target.
if(NOT TARGET Qt6::XmlPatterns)
find_package(Qt6XmlPatterns QUIET)
if(Qt6XmlPatterns_FOUND)
message(STATUS "Found Qt6XmlPatterns")
else()
message(STATUS "Qt6XmlPatterns not found (PpmMSDLGuiPlugin/PpmSAABGuiPlugin require it; keep BUILD_PLUGINS_MSDL/BUILD_PLUGINS_SAAB OFF)")
endif()
endif()
# MSDL/Saab import libs (gated by BUILD_PLUGINS_MSDL / BUILD_PLUGINS_SAAB) no
# longer use Qt XmlPatterns (QXmlSchema/QXmlSchemaValidator), which was removed
# in Qt 6.0. They were re-implemented with Qt6::Xml (QDomDocument) for the
# schema well-formedness check plus the external xmllint step for real XSD
# validation; MSDL additionally links XercesC and uses xsdc++-generated tree
# classes. No Qt6::XmlPatterns lookup is needed any more.
# Qt6::WebChannel (consumed by PpmOrgChartGuiPlugin's QWebChannel page setup):
# in Qt5 Qt5::WebEngineWidgets transitively linked Qt5::WebChannel (Qt5's
@@ -6,7 +6,7 @@
#
ADD_SUBDIRECTORY(Common)
# MSDL requires XmlPatterns - skip for Qt6 migration baseline
# MSDL re-implemented without Qt XmlPatterns (Qt6::Xml + XercesC/xsdc++ + xmllint)
IF(BUILD_PLUGINS_MSDL)
ADD_SUBDIRECTORY(MSDL)
ENDIF()
@@ -21,7 +21,7 @@ ADD_SUBDIRECTORY(ParticipantSelection)
ADD_SUBDIRECTORY(ParticipantTemplates)
ADD_SUBDIRECTORY(PartyEdit)
ADD_SUBDIRECTORY(PpmComboBox)
# Saab requires XmlPatterns - skip for Qt6 migration baseline
# Saab re-implemented without Qt XmlPatterns (Qt6::Xml only)
IF(BUILD_PLUGINS_SAAB)
ADD_SUBDIRECTORY(Saab)
ENDIF()
@@ -79,6 +79,9 @@ INSTALL_SHARED_FILES(zwmsmsdl_SRCS
WS
)
# .ui files live in the ui/ subdirectory; tell AUTOUIC where to find them
set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/ui)
NGL_WRAP_UI(zwmsmsdl_SRCS ${zwmsmsdl_UICS})
NGL_ADD_LIBRARY2(WS zwmsmsdl SHARED ${zwmsmsdl_SRCS} ${zwmsmsdl_UICS} ${zwmsmsdl_IDLS})
NGL_TARGET_INCLUDE_DIRECTORIES(zwmsmsdl
@@ -93,7 +96,6 @@ if(QT6_GUI_AVAILABLE)
PRIVATE
${Qt6_Gui}
Qt6::Xml
Qt6::XmlPatterns
XercesC::XercesC
PUBLIC
svcPpmCommon
@@ -184,7 +184,7 @@ msdl_1::MilitaryScenarioType::ForceSides_type Private::createTagForceSides(const
for (const ParticipantManagement::Party &party : mapForces)
{
if (party.id() == 0 || party.id() == 1)
if (party.id == 0 || party.id == 1)
continue;
QString obHaStr = QUuid::createUuid().toString();
@@ -202,7 +202,7 @@ msdl_1::MilitaryScenarioType::ForceSides_type Private::createTagForceSides(const
const ParticipantManagement::Party &party = itForce.value();
msdl_1::ForceSideType::ObjectHandle_type obHaTy(strUUID.toStdString().c_str());
msdl_1::ForceSideType::ForceSideName_type foSiNaTy(party.name().c_str());
msdl_1::ForceSideType::ForceSideName_type foSiNaTy(party.name.c_str());
msdl_1::ForceSideType foSiTy(obHaTy, foSiNaTy);
@@ -218,7 +218,7 @@ msdl_1::MilitaryScenarioType::ForceSides_type Private::createTagForceSides(const
ParticipantManagement::Role role = itRelationship.value().role();
ParticipantManagement::Role role = itRelationship.value().role;
msdl_1::ForceSideType::Associations_type::Association_type::Relationship_type relType = msdl_1::ForceSideType::Associations_type::Association_type::Relationship_type::UNK;
if (role == ParticipantManagement::Role::Enemy)
@@ -238,7 +238,7 @@ msdl_1::MilitaryScenarioType::ForceSides_type Private::createTagForceSides(const
foSiTy.Associations(asType);
foSiSe.push_back(foSiTy);
mapForceHandles[party.id()] = strUUID;
mapForceHandles[party.id] = strUUID;
}
return foType;
@@ -315,7 +315,7 @@ msdl_1::MilitaryScenarioType::Organizations_type::Units_type Private::createTagU
QString obHaStr = QUuid::createUuid().toString();
obHaStr = obHaStr.mid(1, obHaStr.size() - 2);
mapParticipantsUUIDs[participant.id()] = obHaStr.toStdString();
mapParticipantsUUIDs[participant.id] = obHaStr.toStdString();
}
unitsType unitsTy;
@@ -326,16 +326,16 @@ msdl_1::MilitaryScenarioType::Organizations_type::Units_type Private::createTagU
for (const ParticipantManagement::Participant &participant : mapParticipants)
{
if (participant.partyId() != it.key())
if (participant.partyId != it.key())
continue;
if (participant.isDeleted())
if (participant.isDeleted)
continue;
forceRelationDataType foReDaTy;
forceRelationChoiceType foReChTy = forceRelationChoiceType::FORCE_SIDE;
if (participant.superiorId() == 0)
if (participant.superiorId == 0)
{
foReChTy = forceRelationChoiceType::FORCE_SIDE;
@@ -346,12 +346,12 @@ msdl_1::MilitaryScenarioType::Organizations_type::Units_type Private::createTagU
{
foReChTy = forceRelationChoiceType::UNIT;
msdl_1::CommandRelationType::CommandingSuperiorHandle_type handle(mapParticipantsUUIDs.value(participant.superiorId()));
msdl_1::CommandRelationType::CommandingSuperiorHandle_type handle(mapParticipantsUUIDs.value(participant.superiorId));
forceRelationDataType::CommandRelation_type cmdRelation(handle, msdl_1::CommandRelationType::CommandRelationshipType_type::TACON);
foReDaTy.CommandRelation(cmdRelation);
}
unitType::ObjectHandle_type unObHaTy(mapParticipantsUUIDs.value(participant.id()));
unitType::ObjectHandle_type unObHaTy(mapParticipantsUUIDs.value(participant.id));
unitType::SymbolIdentifier_type syIdTy = "S--------------";
relationsType::ForceRelation_type foReTy(foReChTy, foReDaTy);
@@ -360,7 +360,7 @@ msdl_1::MilitaryScenarioType::Organizations_type::Units_type Private::createTagU
unitType unitTy(unObHaTy, syIdTy, reTy);
unitTy.SymbolIdentifier(syIdTy);
unitType::Name_type naTy(participant.designator().c_str());
unitType::Name_type naTy(participant.designator.c_str());
unitTy.Name(naTy);
unSe.push_back(unitTy);
@@ -389,16 +389,16 @@ msdl_1::MilitaryScenarioType::Organizations_type::Equipment_type Private::create
for (const ParticipantManagement::Participant &participant : mapParticipants)
{
if (participant.partyId() != partyId)
if (participant.partyId != partyId)
continue;
if (participant.isDeleted())
if (participant.isDeleted)
continue;
ownerDataType::UnitOwnerHandle_type foOwHaTy;
foOwHaTy = mapParticipantsUUIDs.value(participant.id()).c_str();
foOwHaTy = mapParticipantsUUIDs.value(participant.id).c_str();
ownerDataType owDaTy;
owDaTy.UnitOwnerHandle(foOwHaTy);
@@ -409,11 +409,11 @@ msdl_1::MilitaryScenarioType::Organizations_type::Equipment_type Private::create
auto vecDISEntities = mapTypes.value(participant.typeId()).disEntities();
auto vecDISEntities = mapTypes.value(participant.typeId).disEntities;
if (!vecDISEntities.size())
{
WARNING_LOG(logger) << "Participant id " << participant.id()
<< " belongs to a type id " << participant.typeId() << " which has no DIS id! Skipping export of participant!";
WARNING_LOG(logger) << "Participant id " << participant.id
<< " belongs to a type id " << participant.typeId << " which has no DIS id! Skipping export of participant!";
continue;
}
@@ -425,9 +425,9 @@ msdl_1::MilitaryScenarioType::Organizations_type::Equipment_type Private::create
coordDataType::GCC_type::X_type x(mapParticipantPositions[participant.id()].pos().lon());
coordDataType::GCC_type::X_type y(mapParticipantPositions[participant.id()].pos().lat());
coordDataType::GCC_type::Z_type z(mapParticipantPositions[participant.id()].pos().z());
coordDataType::GCC_type::X_type x(mapParticipantPositions[participant.id].pos.lon);
coordDataType::GCC_type::X_type y(mapParticipantPositions[participant.id].pos.lat);
coordDataType::GCC_type::Z_type z(mapParticipantPositions[participant.id].pos.z);
coordDataType::GCC_type utTy(x, y, z);
coordDataType coDaTy;
@@ -459,7 +459,7 @@ msdl_1::MilitaryScenarioType::Organizations_type::Equipment_type Private::create
eqItTy.ObjectHandle(eqObHaTy);
equipItemType::Name_type naTy(mapEquipment.value(mapTypes.value(participant.typeId()).equipmentTypeId()).name());
equipItemType::Name_type naTy(mapEquipment.value(mapTypes.value(participant.typeId).equipmentTypeId).name);
eqItTy.Name(naTy);
eqItTy.SymbolIdentifier(syIdTy);
@@ -22,21 +22,21 @@ ScenarioDataDialog::ScenarioDataDialog(QWidget *parent,
connect(mUi->m_pushButton_Cancel, &QPushButton::clicked, this, &ScenarioDataDialog::onButtonCancel);
ExerciseManagement::Exercise exercise = exmDtc->exercise(pSession->exerciseId());
mUi->m_lineEdit_ExerciseDescription->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("exerciseDescription"), QString::fromStdString(exercise.description())).toString());
mUi->m_lineEdit_ExerciseDescription->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("exerciseDescription"), QString::fromStdString(exercise.description)).toString());
QString strName(QString::fromStdString(exercise.name()));
QString strName(QString::fromStdString(exercise.name));
strName.remove(QLatin1Char(' '));
mUi->m_lineEdit_ExerciseName->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("exerciseName"), strName).toString());
mUi->m_lineEdit_Domain->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("exerciseDomain"), QString::fromStdString(exercise.partitionName())).toString());
mUi->m_lineEdit_Domain->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("exerciseDomain"), QString::fromStdString(exercise.partitionName)).toString());
mUi->m_lineEdit_Version->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("exerciseVersion"), QString()).toString());
mUi->m_lineEdit_Purpose->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("exercisePurpose"), QString()).toString());
OperatorManagement::User user = opmDtc->user(LtsSessionData::LtsSessionData::getInstance()->getOperatorId());
mUi->m_lineEdit_Type->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("pocType"), QString::fromStdString(user.description())).toString());
mUi->m_lineEdit_AuthorName->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("pocAuthor"), QString::fromStdString(user.name())).toString());
mUi->m_lineEdit_Type->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("pocType"), QString::fromStdString(user.description)).toString());
mUi->m_lineEdit_AuthorName->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("pocAuthor"), QString::fromStdString(user.name)).toString());
mUi->m_lineEdit_Organization->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("pocOrganization"), QString()).toString());
mUi->m_lineEdit_Email->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("pocEmail"), QString()).toString());
mUi->m_lineEdit_Telephone->setText(LtsUtils::OperatorSettings::getInstance()->value(QStringLiteral("MSDL"), QStringLiteral("pocTelephone"), QString()).toString());
@@ -17,12 +17,9 @@
#include <QtCore/QUuid>
#include <QtCore/QTextStream>
#include <QtCore/QUrl>
#include <QAbstractMessageHandler>
#include <QtXml/QDomDocument>
#include <QMimeData>
#include <QtCore/QProcess>
#include <QtXmlPatterns/QXmlSchema>
#include <QtXmlPatterns/QXmlSchemaValidator>
#include <ngltools/ngltools_filesystem.h>
#include <Common/participant_dis_helper.h>
@@ -89,17 +86,17 @@ ImportMsdl::ImportMsdl(ParticipantManagement::ParticipantEditModel *pModel, cons
for (const ParticipantManagement::Type &type : std::as_const(m_mapTypes))
{
for (const auto &disId : type.disEntities())
for (const auto &disId : type.disEntities)
{
QString strMSDL_DISId = ParticipantManagement::DIS::convertDISTypeInteger2MSDLString(disId);
if (m_mapMSDL_DIS_2TypeId.find(strMSDL_DISId) != m_mapMSDL_DIS_2TypeId.end())
{
WARNING_LOG(mLogger) << "DIS id \"" << strMSDL_DISId << "\" which is assigned to type id \"" << type.id() << "\" is already assigned to type id \"" << m_mapMSDL_DIS_2TypeId[strMSDL_DISId] << "\"";
WARNING_LOG(mLogger) << "DIS id \"" << strMSDL_DISId << "\" which is assigned to type id \"" << type.id << "\" is already assigned to type id \"" << m_mapMSDL_DIS_2TypeId[strMSDL_DISId] << "\"";
continue;
}
m_mapMSDL_DIS_2TypeId[strMSDL_DISId] = type.id();
m_mapMSDL_DIS_2TypeId[strMSDL_DISId] = type.id;
}
}
}
@@ -286,13 +283,14 @@ bool ImportMsdl::schemaValidation()
return false;
}
QXmlSchema schema;
msdl::SchemaMessageHandler smh;
schema.setMessageHandler(&smh);
schema.load(&schemaFile, QUrl::fromLocalFile(schemaFile.fileName()));
// Qt6: Qt XmlPatterns (QXmlSchema) was removed. Check the schema file is
// well-formed XML via Qt6::Xml (QDomDocument); the external xmllint step below
// performs the full schema/instance validation.
QDomDocument schemaDoc;
schemaDoc.setContent(&schemaFile, false);
if (!schema.isValid())
if (schemaDoc.documentElement().isNull())
{
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Schema is invalid"));
return false;
@@ -322,16 +320,6 @@ bool ImportMsdl::schemaValidation()
#endif
QXmlSchemaValidator validator(schema);
if (false )
{
#ifdef LTS_DEBUG
LtsWidgets::LtsMessageDialog::showMessage(this, tr("Instance document is invalid"));
#endif
return false;
}
return true;
}
@@ -341,17 +329,14 @@ ParticipantManagement::ParticipantData ImportMsdl::createParticipant(const MSDLP
ParticipantManagement::ParticipantData p;
p.designator(unit.m_designator.toStdString());
p.tacticalIdentifier(unit.m_tacticalIdentifier.toStdString());
p.designator = unit.m_designator.toStdString();
p.tacticalIdentifier = unit.m_tacticalIdentifier.toStdString();
p.equipmentNumber() = 0;
p.assignState() = ParticipantManagement::ParticipantAssignState::HandoutExcon;
p.equipmentNumber = 0;
p.assignState = ParticipantManagement::ParticipantAssignState::HandoutExcon;
p.symbol(m_mapTypes[unit.m_mappedTypeId].symbol());
p.typeId(unit.m_mappedTypeId);
p.symbol = m_mapTypes[unit.m_mappedTypeId].symbol;
p.typeId = unit.m_mappedTypeId;
return p;
}
@@ -370,7 +355,7 @@ void ImportMsdl::insertParty(const MSDLParty &party)
{
ParticipantManagement::ParticipantData newParty;
newParty.designator(party.m_forceSideName.toStdString());
newParty.designator = party.m_forceSideName.toStdString();
createNode(newParty, m_indexRoot, party.m_ownHandle);
}
@@ -753,7 +738,7 @@ void ImportMsdl::mapParticipant2Type(MSDLParticipant &participant, qint32 mapped
{
m_mapMSDL_DIS_2TypeId[participant.m_DISTypeMSDL] = mappedTypeId;
m_mapTypes[mappedTypeId].disEntities().push_back(ParticipantManagement::DIS::convertMSDLString2Integer(participant.m_DISTypeMSDL));
m_mapTypes[mappedTypeId].disEntities.push_back(ParticipantManagement::DIS::convertMSDLString2Integer(participant.m_DISTypeMSDL));
m_setTouchedTypes.insert(mappedTypeId);
}
}
@@ -182,18 +182,3 @@ void ImportMsdlShow::slotCustomContextMenuActionTriggered(QAction *ac)
}
void SchemaMessageHandler::handleMessage(QtMsgType type,
const QString &description,
const QUrl &identifier,
const QSourceLocation &sourceLocation)
{
ERROR_LOG(mLogger) << "type: " << type << " desc: " << description;
if (identifier.isValid())
ERROR_LOG(mLogger) << "identifier: " << identifier.toString();
if (!sourceLocation.isNull())
ERROR_LOG(mLogger) << "sourceLocation: "
<< sourceLocation.uri().toString()
<< " line: " << sourceLocation.line()
<< " column: " << sourceLocation.column()
;
}
@@ -4,7 +4,6 @@
#pragma once
#include <QtXml/QDomDocument>
#include <QtXmlPatterns/QAbstractMessageHandler>
#include <nglwidgets/ngldialog.h>
#include "msdl_logging.h"
@@ -13,23 +12,6 @@
namespace msdl
{
class SchemaMessageHandler : public QAbstractMessageHandler
{
Q_OBJECT
public:
explicit SchemaMessageHandler(QObject *parent = nullptr)
: QAbstractMessageHandler(parent)
, mLogger(getLogger("SchemaMessageHandler"))
{}
protected:
void handleMessage(QtMsgType type,
const QString &description,
const QUrl &identifier = QUrl(),
const QSourceLocation &sourceLocation = QSourceLocation()) override;
private:
LOGGER_T mLogger;
};
class ImportMsdlShow : public NGLDialog
{
Q_OBJECT
@@ -26,13 +26,13 @@ MappingDialog::MappingDialog(QWidget *parent, bool typeClassIsUnit, const QStrin
for (const ParticipantManagement::Type &type : std::as_const(m_mapTypes))
{
if (!m_offerDatabaseEntriesWithoutDISType && (type.disEntities().size() == 0))
if (!m_offerDatabaseEntriesWithoutDISType && (type.disEntities.size() == 0))
{
WARNING_LOG(mLogger) << "Type id " << type.id() << " does not have assigned DIS types! Type cannot be used when importing MSDL data!";
WARNING_LOG(mLogger) << "Type id " << type.id << " does not have assigned DIS types! Type cannot be used when importing MSDL data!";
continue;
}
const ParticipantManagement::TypeClass typeClassId = type.typeClass();
const ParticipantManagement::TypeClass typeClassId = type.typeClass;
if (typeClassIsUnit)
{
@@ -49,7 +49,7 @@ MappingDialog::MappingDialog(QWidget *parent, bool typeClassIsUnit, const QStrin
}
for (const auto &typeclass : setTypeClasses)
mUi->m_ltsComboBox_typeClass->addItem(ParticipantManagement::toString(typeclass), typeclass);
mUi->m_ltsComboBox_typeClass->addItem(ParticipantManagement::toString(typeclass), static_cast<int>(typeclass));
slotClassTypeChanged();
@@ -68,21 +68,21 @@ void MappingDialog::slotClassTypeChanged()
{
mUi->m_ltsComboBox_type->clear();
int currentClass = mUi->m_ltsComboBox_typeClass->currentData().toInt();
ParticipantManagement::TypeClass currentClass = static_cast<ParticipantManagement::TypeClass>(mUi->m_ltsComboBox_typeClass->currentData().toInt());
for (const ParticipantManagement::Type &type : std::as_const(m_mapTypes))
{
if (type.typeClass() != currentClass)
if (type.typeClass != currentClass)
continue;
if (!m_offerDatabaseEntriesWithoutDISType && (type.disEntities().size() == 0))
if (!m_offerDatabaseEntriesWithoutDISType && (type.disEntities.size() == 0))
{
WARNING_LOG(mLogger) << "Type id " << type.id() << " does not have assigned DIS types! Type cannot be used when importing MSDL data!";
WARNING_LOG(mLogger) << "Type id " << type.id << " does not have assigned DIS types! Type cannot be used when importing MSDL data!";
continue;
}
mUi->m_ltsComboBox_type->addItem(QString::fromStdString(type.name()), type.id());
mUi->m_ltsComboBox_type->addItem(QString::fromStdString(type.name), type.id);
}
}
@@ -122,6 +122,6 @@ bool MappingDialog::autoMapAllUnmappedElements() const
int32_t MappingDialog::getMappedTypeId() const
{
int index = mUi->m_ltsComboBox_type->currentData().toInt();
return m_mapTypes[index].id();
return m_mapTypes[index].id;
}
}
@@ -3,7 +3,7 @@
#include "ppm_msdl_edit.h"
#include "ui_ppm_msdl_edit.h"
#include "msdl/msdl_import.h"
#include "msdl_export.h"
#include "msdl/msdl_export.h"
#include <QtGui/QAction>
#include <AdvancedSymbology/asb_data_plugin_interface.h>
@@ -18,6 +18,7 @@ namespace ParticipantManagement
{
MSDLEdit::MSDLEdit(LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_logger(getLogger("MSDLEdit"))
, m_actionRemove(nullptr)
, m_actionEdit(nullptr)
, m_ppmDtc(nullptr)
@@ -3,7 +3,7 @@
#include "ppm_saab_edit.h"
#include "ui_ppm_saab_edit.h"
#include "saab/saab_import.h"
#include "saab_export.h"
#include "saab/saab_export.h"
#include <QtGui/QAction>
#include <AdvancedSymbology/asb_data_plugin_interface.h>
@@ -18,6 +18,7 @@ namespace ParticipantManagement
{
SAABEdit::SAABEdit(LtsSession::LtsSession *session, QWidget *parent)
: LtsWidgets::LtsDialog(parent, LtsWidgets::ButtonCombination::OkApplyCancel)
, m_logger(getLogger("SAABEdit"))
, m_actionRemove(nullptr)
, m_actionEdit(nullptr)
, m_ppmDtc(nullptr)
@@ -43,6 +43,9 @@ SET(zwmssaab_UICS
ui/saab_mapping_dialog.ui
)
# .ui files live in the ui/ subdirectory; tell AUTOUIC where to find them
set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/ui)
NGL_WRAP_UI(zwmssaab_SRCS ${zwmssaab_UICS})
NGL_ADD_LIBRARY2(WS zwmssaab SHARED ${zwmssaab_SRCS} ${zwmssaab_UICS} ${zwmssaab_IDLS})
NGL_TARGET_INCLUDE_DIRECTORIES(zwmssaab
@@ -55,7 +58,6 @@ if(QT6_GUI_AVAILABLE)
PRIVATE
${Qt6_Gui}
Qt6::Xml
Qt6::XmlPatterns
PUBLIC
svcPpmCommon
LtsUtilsSettings
@@ -45,6 +45,7 @@ ExportSaab::ExportSaab(LtsSession::LtsSession *session, const std::shared_ptr<Pa
, m_session(session)
, m_configFile(nullptr)
, m_ui(new Ui_SAABExport)
, m_logger(saab::getLogger("ExportSaab"))
{
m_ui->setupUi(this);
@@ -369,13 +370,13 @@ void ExportSaab::writeExercise(QXmlStreamWriter *writer) const
using namespace XmlStrings;
writer->writeStartElement(SAAB_EXERCISE());
writer->writeAttribute(SAAB_ID(), QUuid(l, m_currentExercise.id(), w2, b1, b2, b3, b4, b5, b6, b7, GuidContext::GuidExercise).toString(QUuid::WithoutBraces));
writer->writeAttribute(SAAB_ID(), QUuid(l, m_currentExercise.id, w2, b1, b2, b3, b4, b5, b6, b7, GuidContext::GuidExercise).toString(QUuid::WithoutBraces));
writer->writeTextElement(SAAB_EXPORT_TIME(), toSaabTime(m_session->partitionTime()));
writer->writeTextElement(SAAB_PLANNED_START_TIME(), toSaabTime(m_currentExercise.beginTime()));
writer->writeTextElement(SAAB_PLANNED_STOP_TIME(), toSaabTime(m_currentExercise.endTime()));
writer->writeTextElement(SAAB_DESIGNATION(), QString::fromStdString(m_currentExercise.name()));
writer->writeTextElement(SAAB_DESCRIPTION(), QString::fromStdString(m_currentExercise.description()));
writer->writeTextElement(SAAB_PLANNED_START_TIME(), toSaabTime(m_currentExercise.beginTime));
writer->writeTextElement(SAAB_PLANNED_STOP_TIME(), toSaabTime(m_currentExercise.endTime));
writer->writeTextElement(SAAB_DESIGNATION(), QString::fromStdString(m_currentExercise.name));
writer->writeTextElement(SAAB_DESCRIPTION(), QString::fromStdString(m_currentExercise.description));
writer->writeTextElement(SAAB_WIND_SPEED(), QStringLiteral("0"));
writer->writeTextElement(SAAB_WIND_DIRECTION(), QStringLiteral("0"));
writer->writeEmptyElement(SAAB_EVALUATION_PACKAGE_FILE_NAME());
@@ -420,13 +421,13 @@ SaabPlayer *ExportSaab::toSaabPlayer(const ParticipantManagement::Party &party,
result = new SaabUnit;
result->symbol = m_mapPartyToForce.value(party.id()).symbolCode;
static_cast<SaabUnit *>(result)->unitSize = m_mapPartyToForce.value(party.id()).echelonCode;
result->designation = QString::fromStdString(party.name());
result->symbol = m_mapPartyToForce.value(party.id).symbolCode;
static_cast<SaabUnit *>(result)->unitSize = m_mapPartyToForce.value(party.id).echelonCode;
result->designation = QString::fromStdString(party.name);
result->trashcan = false;
result->isExternalPlayer = true;
result->force = m_mapPartyToForce.value(party.id()).forceCode;
result->guid = QUuid(l, m_currentExercise.id(), w2, static_cast<uchar>(party.id()), b2, b3, b4, b5, b6, b7, GuidContext::GuidParty).toString(QUuid::WithoutBraces);
result->force = m_mapPartyToForce.value(party.id).forceCode;
result->guid = QUuid(l, m_currentExercise.id, w2, static_cast<uchar>(party.id), b2, b3, b4, b5, b6, b7, GuidContext::GuidParty).toString(QUuid::WithoutBraces);
QList<int> keys = remainingParticipants.keys();
@@ -438,7 +439,7 @@ SaabPlayer *ExportSaab::toSaabPlayer(const ParticipantManagement::Party &party,
ParticipantManagement::Participant participant = remainingParticipants.value(key);
if (!(participant.partyId() == party.id() && participant.superiorId() == 0))
if (!(participant.partyId == party.id && participant.superiorId == 0))
continue;
SaabPlayer *player = toSaabPlayer(participant, remainingParticipants);
@@ -454,26 +455,26 @@ SaabPlayer *ExportSaab::toSaabPlayer(const ParticipantManagement::Party &party,
SaabPlayer *ExportSaab::toSaabPlayer(const ParticipantManagement::Participant &participant, QMap<int, ParticipantManagement::Participant> &remainingParticipants)
{
if (participant.isDeleted())
if (participant.isDeleted)
{
DEBUG_LOG(m_logger) << "Participant with id " << participant.id() << " id deleted --> skipping";
DEBUG_LOG(m_logger) << "Participant with id " << participant.id << " id deleted --> skipping";
return nullptr;
}
if (participant.externalId())
if (participant.externalId)
{
DEBUG_LOG(m_logger) << "Particpant with id " << participant.id() << " has external ID set to " << participant.externalId() << " --> not being exported.";
DEBUG_LOG(m_logger) << "Particpant with id " << participant.id << " has external ID set to " << participant.externalId << " --> not being exported.";
return nullptr;
}
SaabPlayer *result;
ParticipantManagement::Type type = m_types.value(participant.typeId());
ParticipantManagement::Type type = m_types.value(participant.typeId);
if (!m_mapTypeToSaabSymbol.contains(type.id()))
if (!m_mapTypeToSaabSymbol.contains(type.id))
mapType(type);
switch (type.typeClass())
switch (type.typeClass)
{
case ParticipantManagement::TypeClass::SupportEntity:
result = new SaabOcPlayer;
@@ -491,9 +492,9 @@ SaabPlayer *ExportSaab::toSaabPlayer(const ParticipantManagement::Participant &p
{
result = new SaabUnit;
DEBUG_LOG(m_logger) << "Reading unit with " << participant.inferiorIds().size() << " inferiors";
DEBUG_LOG(m_logger) << "Reading unit with " << participant.inferiorIds.size() << " inferiors";
for (int32_t id : participant.inferiorIds())
for (int32_t id : participant.inferiorIds)
{
SaabPlayer *player = toSaabPlayer(remainingParticipants.value(id), remainingParticipants);
@@ -509,7 +510,7 @@ SaabPlayer *ExportSaab::toSaabPlayer(const ParticipantManagement::Participant &p
if (!static_cast<SaabUnit *>(result)->inferiors.size())
{
DEBUG_LOG(m_logger) << "Unit " << participant.id() << " has no inferiors.";
DEBUG_LOG(m_logger) << "Unit " << participant.id << " has no inferiors.";
return nullptr;
}
@@ -519,11 +520,11 @@ SaabPlayer *ExportSaab::toSaabPlayer(const ParticipantManagement::Participant &p
case ParticipantManagement::TypeClass::Aircraft:
case ParticipantManagement::TypeClass::Unknown:
default:
DEBUG_LOG(m_logger) << "Type " << participant.typeId() << " is not supported.";
DEBUG_LOG(m_logger) << "Type " << participant.typeId << " is not supported.";
return nullptr;
}
QString symbol = m_mapTypeToSaabSymbol.value(type.id());
QString symbol = m_mapTypeToSaabSymbol.value(type.id);
if (typeid(*result) == typeid(SaabUnit))
{
@@ -535,22 +536,22 @@ SaabPlayer *ExportSaab::toSaabPlayer(const ParticipantManagement::Participant &p
else
result->symbol = symbol;
result->designation = QString::fromStdString(participant.designator());
result->trashcan = participant.isDeleted();
result->designation = QString::fromStdString(participant.designator);
result->trashcan = participant.isDeleted;
result->rank = QStringLiteral("OF1");
result->isExternalPlayer = true;
if (participant.equipmentNumber().has_value())
result->simulatorId = participant.equipmentNumber().get();
result->force = m_mapPartyToForce.value(participant.partyId()).forceCode;
result->guid = QUuid(participant.id(), m_currentExercise.id(), w2, static_cast<uchar>(participant.partyId()), b2, b3, b4, b5, b6, b7, GuidContext::GuidParticipant).toString(QUuid::WithoutBraces);
if (participant.equipmentNumber.has_value())
result->simulatorId = participant.equipmentNumber.get();
result->force = m_mapPartyToForce.value(participant.partyId).forceCode;
result->guid = QUuid(participant.id, m_currentExercise.id, w2, static_cast<uchar>(participant.partyId), b2, b3, b4, b5, b6, b7, GuidContext::GuidParticipant).toString(QUuid::WithoutBraces);
return result;
}
ParticipantManagement::Participant ExportSaab::rootParticipant(const ParticipantManagement::Participant &participant, const QMap<int, ParticipantManagement::Participant> &participants) const
{
if (participant.superiorId())
return rootParticipant(participants.value(participant.superiorId()), participants);
if (participant.superiorId)
return rootParticipant(participants.value(participant.superiorId), participants);
return participant;
}
@@ -563,10 +564,10 @@ void ExportSaab::mapType(const ParticipantManagement::Type &type)
{
using namespace ParticipantManagement;
MapType dialog(ParticipantManagement::trTypeName(type.name()),
MapType dialog(ParticipantManagement::trTypeName(type.name),
m_mapEchelons,
m_mapSymbols,
type.typeClass() == TypeClass::Unit || type.typeClass() == TypeClass::SupportUnit,
type.typeClass == TypeClass::Unit || type.typeClass == TypeClass::SupportUnit,
this);
dialog.exec();
@@ -579,19 +580,19 @@ void ExportSaab::mapType(const ParticipantManagement::Type &type)
saabTypeStr.append(dialog.echelonCode());
}
m_mapTypeToSaabSymbol.insert(type.id(), saabTypeStr);
m_mapTypeToSaabSymbol.insert(type.id, saabTypeStr);
}
void ExportSaab::mapPartyToForce(const ParticipantManagement::Party &party)
{
MapParty dialog(QString::fromStdString(party.name()), m_mapForces, m_mapEchelons, m_mapSymbols, this);
MapParty dialog(QString::fromStdString(party.name), m_mapForces, m_mapEchelons, m_mapSymbols, this);
dialog.exec();
if (dialog.isSkipped())
return;
m_mapPartyToForce.insert(party.id(), { m_mapForces.take(dialog.force()), dialog.echelonCode(), dialog.symbolCode() });
m_mapPartyToForce.insert(party.id, { m_mapForces.take(dialog.force()), dialog.echelonCode(), dialog.symbolCode() });
}
}
@@ -166,17 +166,16 @@ ParticipantManagement::ParticipantData ImportSaab::createParticipant(SaabPlayer
p.tacticalIdentifier(player->designation.toStdString());
p.tacticalIdentifier = player->designation.toStdString();
p.equipmentNumber(player->simulatorId != INT_MIN ? player->simulatorId : 0);
p.assignState() = ParticipantManagement::ParticipantAssignState::HandoutExcon;
p.equipmentNumber = (player->simulatorId != INT_MIN ? player->simulatorId : 0);
p.assignState = ParticipantManagement::ParticipantAssignState::HandoutExcon;
if (player->simulatorId != INT_MIN)
p.externalId(player->simulatorId);
p.externalId = player->simulatorId;
p.symbol(m_mapTypes[player->mappedTypeId].symbol());
p.typeId(player->mappedTypeId);
p.symbol = m_mapTypes[player->mappedTypeId].symbol;
p.typeId = player->mappedTypeId;
return p;
}
@@ -192,7 +191,7 @@ void ImportSaab::insertParty(SaabUnit *party)
{
ParticipantManagement::ParticipantData newParty;
newParty.designator(party->designation.toStdString());
newParty.designator = party->designation.toStdString();
createNode(newParty, m_indexRoot, party);
}
@@ -182,18 +182,3 @@ void ImportSaabShow::slotCustomContextMenuActionTriggered(QAction *ac)
}
void SchemaMessageHandler::handleMessage(QtMsgType type,
const QString &description,
const QUrl &identifier,
const QSourceLocation &sourceLocation)
{
ERROR_LOG(mLogger) << "type: " << type << " desc: " << description;
if (identifier.isValid())
ERROR_LOG(mLogger) << "identifier: " << identifier.toString();
if (!sourceLocation.isNull())
ERROR_LOG(mLogger) << "sourceLocation: "
<< sourceLocation.uri().toString()
<< " line: " << sourceLocation.line()
<< " column: " << sourceLocation.column()
;
}
@@ -4,7 +4,6 @@
#pragma once
#include <QtXml/QDomDocument>
#include <QtXmlPatterns/QAbstractMessageHandler>
#include <nglwidgets/ngldialog.h>
#include "saab_logging.h"
@@ -13,25 +12,6 @@
namespace saab
{
class SchemaMessageHandler : public QAbstractMessageHandler
{
Q_OBJECT
public:
explicit SchemaMessageHandler(QObject *parent = nullptr)
: QAbstractMessageHandler(parent)
, mLogger(getLogger("SchemaMessageHandler"))
{}
~SchemaMessageHandler()
{}
protected:
void handleMessage(QtMsgType type,
const QString &description,
const QUrl &identifier = QUrl(),
const QSourceLocation &sourceLocation = QSourceLocation());
private:
LOGGER_T mLogger;
};
class ImportSaabShow : public NGLDialog
{
Q_OBJECT
@@ -26,16 +26,16 @@ MappingDialog::MappingDialog(QWidget *parent, bool typeClassIsUnit, const QStrin
for (const ParticipantManagement::Type &type : std::as_const(m_mapTypes))
{
if (!m_offerDatabaseEntriesWithoutDISType && (type.disEntities().size() == 0))
if (!m_offerDatabaseEntriesWithoutDISType && (type.disEntities.size() == 0))
{
WARNING_LOG(mLogger) << "Type id " << type.id() << " does not have assigned DIS types! Type cannot be used when importing SAAB data!";
WARNING_LOG(mLogger) << "Type id " << type.id << " does not have assigned DIS types! Type cannot be used when importing SAAB data!";
continue;
}
if (type.isDeleted())
if (type.isDeleted)
continue;
const ParticipantManagement::TypeClass typeClassId = type.typeClass();
const ParticipantManagement::TypeClass typeClassId = type.typeClass;
if (typeClassId == ParticipantManagement::TypeClass::Unknown ||
typeClassId == ParticipantManagement::TypeClass::Vessel ||
@@ -57,7 +57,7 @@ MappingDialog::MappingDialog(QWidget *parent, bool typeClassIsUnit, const QStrin
}
for (const auto &typeclass : setTypeClasses)
mUi->m_ltsComboBox_typeClass->addItem(ParticipantManagement::toString(typeclass), typeclass);
mUi->m_ltsComboBox_typeClass->addItem(ParticipantManagement::toString(typeclass), static_cast<int>(typeclass));
slotClassTypeChanged();
@@ -76,24 +76,24 @@ void MappingDialog::slotClassTypeChanged()
{
mUi->m_ltsComboBox_type->clear();
int currentClass = mUi->m_ltsComboBox_typeClass->currentData().toInt();
ParticipantManagement::TypeClass currentClass = static_cast<ParticipantManagement::TypeClass>(mUi->m_ltsComboBox_typeClass->currentData().toInt());
for (const ParticipantManagement::Type &type : std::as_const(m_mapTypes))
{
if(type.isDeleted())
if(type.isDeleted)
continue;
if (type.typeClass() != currentClass)
if (type.typeClass != currentClass)
continue;
if (!m_offerDatabaseEntriesWithoutDISType && (type.disEntities().size() == 0))
if (!m_offerDatabaseEntriesWithoutDISType && (type.disEntities.size() == 0))
{
WARNING_LOG(mLogger) << "Type id " << type.id() << " does not have assigned DIS types! Type cannot be used when importing SAAB data!";
WARNING_LOG(mLogger) << "Type id " << type.id << " does not have assigned DIS types! Type cannot be used when importing SAAB data!";
continue;
}
mUi->m_ltsComboBox_type->addItem(QString::fromStdString(type.name()), type.id());
mUi->m_ltsComboBox_type->addItem(QString::fromStdString(type.name), type.id);
}
}
@@ -126,6 +126,6 @@ bool MappingDialog::skipAllUnmappedElements() const
int32_t MappingDialog::getMappedTypeId() const
{
int index = mUi->m_ltsComboBox_type->currentData().toInt();
return m_mapTypes[index].id();
return m_mapTypes[index].id;
}
}
@@ -57,13 +57,15 @@ BUILD_WEBENGINE_PLUGINS:
BUILD_XMLPATTERNS_PLUGINS:
--xmlpatterns-plugins / --no-xmlpatterns-plugins
Enable/disable the XmlPatterns-based plugins (MSDL, Saab)
when Qt6XmlPatterns is present in the Qt install. Qt
removed the XmlPatterns module in Qt 6.0 ("What's New in
Qt 6.0" / Qt Wiki: removed, not planned to be
re-introduced; no Qt 6 release ships it, no aqt
module), so with a stock Qt 6.10.2 install these
plugins stay disabled (environmental floor). (default: ON)
Enable/disable the MSDL/Saab plugins. They no longer
require Qt XmlPatterns (removed in Qt 6.0, not
re-introduced): their import logic was re-implemented
with Qt6::Xml (QDomDocument) + the existing xmllint
step, and MSDL additionally links XercesC + uses
xsdc++-generated tree classes (needs xsdcxx +
libxerces-c-dev, both in APT_PACKAGES). With the
prerequisites present these build by default.
(default: ON)
Build groups:
--group1 / --no-group1 Enable/disable DDS core libraries build
@@ -311,6 +313,19 @@ APT_PACKAGES=(
# uses Poppler types unconditionally, so a green Group 12 build requires it.
pkg-config
libpoppler-qt6-dev
# MSDL/Saab no longer require Qt XmlPatterns (removed in Qt 6.0): their import
# logic was re-implemented with Qt6::Xml (QDomDocument) + the existing xmllint
# schema-validation step. MSDL additionally links XercesC and uses xsdc++-
# generated tree classes, so it needs libxerces-c-dev (XercesC C++ parser) and
# xsdcxx (the xsdc++ code generator, XSD_GENERATE_TREE). Saab only needs
# Qt6::Xml; both are installed together so the two plugins build from the same
# image.
xsdcxx
libxerces-c-dev
# xmllint (libxml2-utils): the MSDL import validates the incoming document against
# its XSD via an external `xmllint --schema` step (QProcess) - pre-existing in the
# legacy (msdl_import.cpp). Provision it so that runtime schema check can run.
libxml2-utils
)
# INTERFACE libraries (header-only) are built automatically as dependencies
@@ -654,15 +669,12 @@ RUN pip3 install --break-system-packages --quiet aqtinstall && \
--outputdir ${QT_BASE_DIR} && \
rm -rf /root/.cache/Aqt
# Qt6 XmlPatterns (MSDL/Saab plugins) is intentionally NOT installed: Qt removed
# the XmlPatterns module in Qt 6.0 ("What's New in Qt 6.0" / Qt Wiki: removed and
# not planned to be re-introduced - unlike e.g. Multimedia/WebEngine which
# returned in 6.1/6.2; no Qt 6 release ships it, no aqt module). Mixing an
# out-of-tree libQt6XmlPatterns built against an older Qt with a 6.10 install
# would put two Qt minor versions in one
# process. MSDL/Saab therefore stay disabled with a stock Qt install; to enable
# them, install a Qt-version-matching XmlPatterns (lib + headers + cmake config)
# into ${QT_BASE_DIR}/${QT_VERSION}/${QT_ARCH_DIR} and pass --xmlpatterns-plugins.
# MSDL/Saab plugins: Qt removed the XmlPatterns module in Qt 6.0 (not re-
# introduced), so their import logic was re-implemented with Qt6::Xml
# (QDomDocument) + the existing external xmllint schema-validation step. MSDL
# additionally links XercesC and uses xsdc++-generated tree classes; xsdcxx +
# libxerces-c-dev are installed via APT_PACKAGES above, so the plugins build with
# a stock Qt 6.10.2 install.
# Install KDReports from source (apt package not available in Ubuntu 22.04/26.04)
# Try apt install first (will fail), then build from KDAB GitHub mirror
@@ -1221,10 +1233,11 @@ GROUP11_TARGETS=(
# BldInfoGuiPlugin - links BuildingViewerCommon (dtEntity/OSG SDK absent)
# BdvViewerGuiPlugin - links BuildingViewerCommon (same floor; CMake skips its
# subdirectory when BuildingViewerCommon is not built)
# PpmMSDLGuiPlugin - links Qt6::XmlPatterns; Qt removed the XmlPatterns
# PpmSAABGuiPlugin - module in Qt 6.0 (not re-introduced; no Qt 6 release
# ships it, incl. 6.10.2). With a stock Qt install the
# BUILD_PLUGINS_MSDL/SAAB flags resolve to OFF (see
# PpmMSDLGuiPlugin / - former XmlPatterns floor, now CLOSED: re-implemented without
# PpmSAABGuiPlugin - Qt XmlPatterns (removed in Qt 6.0) using Qt6::Xml (QDomDocument)
# + the existing xmllint step; MSDL also needs xsdcxx +
# libxerces-c-dev (both in APT_PACKAGES). Now in GROUP12 and built
# by default when the prerequisites are present (see
# resolve_xmlpatterns)
# The Flt*/Smo* targets only exist when BUILD_FILTERMANAGEMENT /
# BUILD_PLUGINS_SERVICEMONITOR are ON (script defaults; see the cmake call).
@@ -1341,12 +1354,14 @@ GROUP12_TARGETS=(
PlanOverlaysGuiPlugin
PpmComboBoxGuiPlugin
PpmDataPlugin
PpmMSDLGuiPlugin
PpmOperationalPlaningGuiPlugin
PpmOrgChartGuiPlugin
PpmParticipantEditGuiPlugin
PpmParticipantInfoGuiPlugin
PpmParticipantTemplatesGuiPlugin
PpmPartyEditGuiPlugin
PpmSAABGuiPlugin
PpmTypeEditGuiPlugin
PpmUasGuiPlugin
PreDataPlugin
@@ -1691,22 +1706,21 @@ if [[ "${BUILD_ARCGIS}" == "ON" ]]; then
fi
fi
# The MSDL/Saab plugins link Qt6::XmlPatterns. Qt removed the XmlPatterns
# module in Qt 6.0 ("What's New in Qt 6.0" removal table / Qt Wiki: removed and
# not planned to be re-introduced - unlike Multimedia/WebEngine, which returned
# in 6.1/6.2). No Qt 6 release (incl. 6.10.2) ships it and there is no aqt
# module. An out-of-tree libQt6XmlPatterns built against an older Qt would mix
# two Qt minor versions in one process (ABI risk), so with a stock Qt install
# the plugins are gated OFF. If a Qt-version-matching XmlPatterns (lib +
# headers + Qt6XmlPatterns cmake config) is placed into the Qt prefix, they
# enable automatically.
# The MSDL/Saab plugins no longer require Qt XmlPatterns (removed in Qt 6.0, not
# re-introduced). Their import logic was re-implemented with Qt6::Xml
# (QDomDocument) plus the existing external xmllint schema-validation step; MSDL
# additionally links XercesC and uses xsdc++-generated tree classes. So build
# them by default. MSDL needs the xsdcxx code generator + libxerces-c-dev (both
# are in APT_PACKAGES); if they are missing here, keep both plugins OFF and flag
# the gap. (Saab only needs Qt6::Xml, but is gated together to keep the effective
# value a single switch.)
resolve_xmlpatterns() {
BUILD_XMLPATTERNS_EFFECTIVE="${BUILD_XMLPATTERNS_PLUGINS}"
if [[ "${BUILD_XMLPATTERNS_EFFECTIVE}" == "ON" ]]; then
if ls "${QT_BASE_DIR}/${QT_VERSION}/${QT_ARCH_DIR}/lib/libQt6XmlPatterns.so.6" >/dev/null 2>&1; then
log_info "Qt6XmlPatterns present in the Qt install - MSDL/Saab plugins will be built"
if command -v xsdcxx >/dev/null 2>&1 && [ -e /usr/lib/x86_64-linux-gnu/libxerces-c.so ]; then
log_info "xsdcxx + XercesC present - MSDL/Saab plugins will be built (re-implemented without Qt XmlPatterns)"
else
log_warn "Qt6XmlPatterns is not present in the Qt install (removed in Qt 6.0, not re-introduced) - keeping BUILD_PLUGINS_MSDL/BUILD_PLUGINS_SAAB OFF (ppm.msdl / ppm.saab stay unbuilt)"
log_warn "xsdcxx / libxerces-c-dev missing - keeping BUILD_PLUGINS_MSDL/BUILD_PLUGINS_SAAB OFF (ppm.msdl / ppm.saab stay unbuilt)"
BUILD_XMLPATTERNS_EFFECTIVE=OFF
fi
fi