diff options
author | Karsten Heimrich <karsten.heimrich@qt.io> | 2018-10-15 14:52:25 +0200 |
---|---|---|
committer | Karsten Heimrich <karsten.heimrich@qt.io> | 2018-10-26 11:15:24 +0000 |
commit | 2a9bb9926d9e4515179b69d70bd579d778980058 (patch) | |
tree | ef4b52aed4126c501ea29b564b9af19add91f1e2 | |
parent | 13e39c059fbf9dd85f52fb0b7c71ad6f419adee0 (diff) |
Fix KNX project parsing for ETS version >= 5.6.*
Task-number: QTBUG-70667
Change-Id: I626755acdbfa7f5bd2f187b5b3fee79346efa0c7
Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
-rw-r--r-- | src/knx/knxproj/qknxbuildings.cpp | 47 | ||||
-rw-r--r-- | src/knx/knxproj/qknxbuildings_p.h | 2 | ||||
-rw-r--r-- | src/knx/knxproj/qknxgroupaddressinfos.cpp | 4 | ||||
-rw-r--r-- | src/knx/knxproj/qknxinstallation.cpp | 21 | ||||
-rw-r--r-- | tests/auto/qknxproject/data/locations.xml | 114 | ||||
-rw-r--r-- | tests/auto/qknxproject/project.qrc | 1 | ||||
-rw-r--r-- | tests/auto/qknxproject/tst_qknxproject.cpp | 13 |
7 files changed, 170 insertions, 32 deletions
diff --git a/src/knx/knxproj/qknxbuildings.cpp b/src/knx/knxproj/qknxbuildings.cpp index 850cf6a..ff81bc1 100644 --- a/src/knx/knxproj/qknxbuildings.cpp +++ b/src/knx/knxproj/qknxbuildings.cpp @@ -140,7 +140,7 @@ bool QKnxBuildingPart::parseElement(QXmlStreamReader *reader, bool pedantic) if (!reader || !reader->isStartElement()) return false; - if (reader->name() == QLatin1String("BuildingPart")) { + if (reader->name() == QLatin1String("BuildingPart") || reader->name() == QLatin1String("Space")) { auto attrs = reader->attributes(); // required attributes @@ -161,14 +161,15 @@ bool QKnxBuildingPart::parseElement(QXmlStreamReader *reader, bool pedantic) QStringLiteral("Building"), QStringLiteral("BuildingPart"), QStringLiteral("Floor"), QStringLiteral("Room"), QStringLiteral("DistributionBoard"), QStringLiteral("Stairway"), - QStringLiteral("Corridor") + QStringLiteral("Corridor"), QStringLiteral("Area"), QStringLiteral("Ground"), + QStringLiteral("Segment") }, &Type, reader, pedantic)) return false; if (!QKnxProjectUtils::fetchAttr(attrs, QStringLiteral("Puid"), &attr, reader)) return false; Puid = attr.toUInt(); - Type = attrs.value(QStringLiteral("Type")).toString(); // TODO: pedantic + Usage = attrs.value(QStringLiteral("Usage")).toString(); // TODO: pedantic Number = attrs.value(QStringLiteral("Number")).toString(); // TODO: pedantic Comment = attrs.value(QStringLiteral("Comment")).toString(); Description = attrs.value(QStringLiteral("Description")).toString(); @@ -184,11 +185,12 @@ bool QKnxBuildingPart::parseElement(QXmlStreamReader *reader, bool pedantic) while (!reader->atEnd() && !reader->hasError()) { auto tokenType = reader->readNext(); if (tokenType == QXmlStreamReader::TokenType::StartElement) { - if (reader->name() == QLatin1String("BuildingPart")) { - QKnxBuildingPart part; - if (!part.parseElement(reader, pedantic)) - return false; - BuildingPart.append(part); + if (reader->name() == QLatin1String("BuildingPart") + || reader->name() == QLatin1String("Space")) { + QKnxBuildingPart part; + if (!part.parseElement(reader, pedantic)) + return false; + BuildingPart.append(part); } else if (reader->name() == QStringLiteral("DeviceInstanceRef")) { QStringRef attr; if (!QKnxProjectUtils::fetchAttr(reader->attributes(), QLatin1String("RefId"), @@ -204,12 +206,15 @@ bool QKnxBuildingPart::parseElement(QXmlStreamReader *reader, bool pedantic) Function.append(function); } } else if (tokenType == QXmlStreamReader::TokenType::EndElement) { - if (reader->name() == QLatin1String("BuildingPart")) + if (reader->name() == QLatin1String("BuildingPart") + || reader->name() == QLatin1String("Space")) { break; + } } } } else { - reader->raiseError(tr("Expected element <BuildingPart>, got: <%1>.").arg(reader->name())); + reader->raiseError(tr("Expected element <BuildingPart> or <Space>, got: <%1>.") + .arg(reader->name())); } return !reader->hasError(); } @@ -222,24 +227,28 @@ bool QKnxBuildings::parseElement(QXmlStreamReader *reader, bool pedantic) if (!reader || !reader->isStartElement()) return false; - if (reader->name() == QLatin1String("Buildings")) { + if (reader->name() == QLatin1String("Buildings") || reader->name() == QLatin1String("Locations")) { // children while (!reader->atEnd() && !reader->hasError()) { auto tokenType = reader->readNext(); if (tokenType == QXmlStreamReader::TokenType::StartElement) { - if (reader->name() == QLatin1String("BuildingPart")) { - QKnxBuildingPart part; - if (!part.parseElement(reader, pedantic)) - return false; - BuildingPart.append(part); + if (reader->name() == QLatin1String("BuildingPart") + || reader->name() == QLatin1String("Space")) { + QKnxBuildingPart part; + if (!part.parseElement(reader, pedantic)) + return false; + BuildingPart.append(part); } } else if (tokenType == QXmlStreamReader::TokenType::EndElement) { - if (reader->name() == QLatin1String("Buildings")) - break; + if (reader->name() == QLatin1String("Buildings") + || reader->name() == QLatin1String("Locations")) { + break; + } } } } else { - reader->raiseError(tr("Expected element <Buildings>, got: <%1>.").arg(reader->name())); + reader->raiseError(tr("Expected element <Buildings> or <Locations>, got: <%1>.") + .arg(reader->name())); } return !reader->hasError(); } diff --git a/src/knx/knxproj/qknxbuildings_p.h b/src/knx/knxproj/qknxbuildings_p.h index 6baa7ef..5d2ad09 100644 --- a/src/knx/knxproj/qknxbuildings_p.h +++ b/src/knx/knxproj/qknxbuildings_p.h @@ -92,7 +92,9 @@ public: QString Id; // non-colonized name, pattern [\i-[:]][\c-[:]]* QString Name; // 255 character max. QString Type; // Building, BuildingPart, Floor, Room, DistributionBoard, Stairway, Corridor + QString Usage; // optional QString Number; // optional, 255 character max. + QString Comment; // optional QString Description; // optional diff --git a/src/knx/knxproj/qknxgroupaddressinfos.cpp b/src/knx/knxproj/qknxgroupaddressinfos.cpp index 87f2e25..510fcab 100644 --- a/src/knx/knxproj/qknxgroupaddressinfos.cpp +++ b/src/knx/knxproj/qknxgroupaddressinfos.cpp @@ -294,7 +294,9 @@ bool QKnxGroupAddressInfos::parse() QZipReader zipReader(&file); const auto fileInfos = zipReader.fileInfoList(); for (const auto &fileInfo : qAsConst(fileInfos)) { - if (fileInfo.filePath.endsWith(QStringLiteral("0.xml"))) + auto file = fileInfo.filePath; + file = file.mid(file.lastIndexOf(QLatin1Char('/'), -5) + 1); + if (file == QStringLiteral("0.xml")) files.insert(fileInfo.filePath); } diff --git a/src/knx/knxproj/qknxinstallation.cpp b/src/knx/knxproj/qknxinstallation.cpp index ed1ef11..c351805 100644 --- a/src/knx/knxproj/qknxinstallation.cpp +++ b/src/knx/knxproj/qknxinstallation.cpp @@ -201,16 +201,17 @@ bool QKnxInstallation::parseElement(QXmlStreamReader *reader, bool pedantic) if (!topology.parseElement(reader, pedantic)) return false; Topology.append(topology); - } else if (reader->name() == QStringLiteral("Buildings")) { - if (pedantic && Buildings.size() >= 1) { - reader->raiseError(tr("Pedantic error: Encountered element " - "<Buildings> more than once.")); - return false; - } - QKnxBuildings buildings; - if (!buildings.parseElement(reader, pedantic)) - return false; - Buildings.append(buildings); + } else if (reader->name() == QStringLiteral("Buildings") + || reader->name() == QStringLiteral("Locations")) { + if (pedantic && Buildings.size() >= 1) { + reader->raiseError(tr("Pedantic error: Encountered element " + "<%1> more than once.").arg(reader->name())); + return false; + } + QKnxBuildings buildings; + if (!buildings.parseElement(reader, pedantic)) + return false; + Buildings.append(buildings); } else if (reader->name() == QStringLiteral("GroupAddresses")) { if (pedantic && GroupAddresses.size() >= 1) { reader->raiseError(tr("Pedantic error: Encountered element " diff --git a/tests/auto/qknxproject/data/locations.xml b/tests/auto/qknxproject/data/locations.xml new file mode 100644 index 0000000..a2ad8a2 --- /dev/null +++ b/tests/auto/qknxproject/data/locations.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="utf-8"?> +<KNX xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + CreatedBy="ETS5" + ToolVersion="5.5.952.23148" + xmlns="http://knx.org/xml/project/14"> + <Project Id="ProjectId"> + <Installations> + <Installation Name="Installation" + BCUKey="4294967295" + DefaultLine="P-01EB-0_L-3" + IPRoutingLatencyTolerance="2000" + CompletionStatus="Undefined" + InstallationId="1" + IPRoutingBackboneKey="12345" + IPRoutingBackboneSecurity="On" + IPRoutingMulticastAddress="192.168.2.1" + IPSyncLatencyFraction="2" + MulticastTTL="25" + SplitType="Master"> + <Locations> + <Space Comment="Comment" + CompletionStatus="Undefined" + DefaultLine="1" + Description="Description" + Id="Id" + Name="Name" + Number="Number" + Puid="1" + Type="Building"> + <Space Comment="Comment2" + CompletionStatus="Editing" + DefaultLine="2" + Description="Description2" + Id="Id2" + Name="Name2" + Number="Number2" + Puid="2" + Type="BuildingPart"> + <DeviceInstanceRef RefId="RefId" /> + <DeviceInstanceRef RefId="RefId2" /> + <Function Comment="Comment" + CompletionStatus="Editing" + DefaultGroupRange="DefaultGroupRange" + Description="Description" + Id="Id3" + Name="Name" + Number="Number" + Puid="3" + Type="Type"> + <GroupAddressRef Id="Id4" + Name="Name" + Puid="4" + RefId="RefId3" + Role="Role"/> + <GroupAddressRef Id="Id5" + Name="Name2" + Puid="5" + RefId="RefId4" + Role="Role2"/> + </Function> + </Space> + <DeviceInstanceRef RefId="RefId5" /> + <DeviceInstanceRef RefId="RefId6" /> + <Function Comment="Comment6" + CompletionStatus="Editing" + DefaultGroupRange="DefaultGroupRange6" + Description="Description6" + Id="Id6" + Name="Name6" + Number="Number6" + Puid="6" + Type="Type6"> + <GroupAddressRef Id="Id7" + Name="Name7" + Puid="7" + RefId="RefId7" + Role="Role7"/> + <GroupAddressRef Id="Id8" + Name="Name8" + Puid="8" + RefId="RefId8" + Role="Role8"/> + </Function> + <Function Comment="Comment9" + CompletionStatus="Editing" + DefaultGroupRange="DefaultGroupRange9" + Description="Description9" + Id="Id9" + Name="Name9" + Number="Number9" + Puid="9" + Type="Type9"> + <GroupAddressRef Id="Id10" + Name="Name10" + Puid="10" + RefId="RefId10" + Role="Role10"/> + <GroupAddressRef Id="Id11" + Name="Name11" + Puid="11" + RefId="RefId11" + Role="Role11"/> + </Function> + </Space> + <Space Id="Id100" + Name="Name100" + Type="Building" + Puid="100" /> + </Locations> + </Installation> + </Installations> + </Project> +</KNX> diff --git a/tests/auto/qknxproject/project.qrc b/tests/auto/qknxproject/project.qrc index cbed69d..2553498 100644 --- a/tests/auto/qknxproject/project.qrc +++ b/tests/auto/qknxproject/project.qrc @@ -4,6 +4,7 @@ <file>data/trades-busaccess-splitinfos.xml</file> <file>data/groupaddresses.xml</file> <file>data/buildings.xml</file> + <file>data/locations.xml</file> <file>data/topology.xml</file> <file>data/unassigneddevices.xml</file> </qresource> diff --git a/tests/auto/qknxproject/tst_qknxproject.cpp b/tests/auto/qknxproject/tst_qknxproject.cpp index 8dc04c4..a9429dd 100644 --- a/tests/auto/qknxproject/tst_qknxproject.cpp +++ b/tests/auto/qknxproject/tst_qknxproject.cpp @@ -449,9 +449,18 @@ private Q_SLOTS: QCOMPARE(address.Security, QLatin1String("Auto")); } - void testBuildings() + void testBuildingsAndLocations_data() { - QFile file(":/data/buildings.xml"); + QTest::addColumn<QString>("path"); + QTest::newRow("Test 'buildings' XML") << ":/data/buildings.xml"; + QTest::newRow("Test 'locations' XML") << ":/data/locations.xml"; + } + + void testBuildingsAndLocations() + { + QFETCH(QString, path); + + QFile file(path); QCOMPARE(file.open(QIODevice::ReadOnly), true); QXmlStreamReader reader(&file); |