summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarsten Heimrich <karsten.heimrich@qt.io>2018-10-15 14:52:25 +0200
committerKarsten Heimrich <karsten.heimrich@qt.io>2018-10-26 11:15:24 +0000
commit2a9bb9926d9e4515179b69d70bd579d778980058 (patch)
treeef4b52aed4126c501ea29b564b9af19add91f1e2
parent13e39c059fbf9dd85f52fb0b7c71ad6f419adee0 (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.cpp47
-rw-r--r--src/knx/knxproj/qknxbuildings_p.h2
-rw-r--r--src/knx/knxproj/qknxgroupaddressinfos.cpp4
-rw-r--r--src/knx/knxproj/qknxinstallation.cpp21
-rw-r--r--tests/auto/qknxproject/data/locations.xml114
-rw-r--r--tests/auto/qknxproject/project.qrc1
-rw-r--r--tests/auto/qknxproject/tst_qknxproject.cpp13
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);