Commit d11cdb14 authored by Friedrich W. H. Kossebau's avatar Friedrich W. H. Kossebau
Browse files

Port JsonPlugin from QtScript to QJson*

parent aa3e0ffe
......@@ -7,8 +7,6 @@ INCLUDE_DIRECTORIES(
set( json_SRCS JsonRunner.cpp JsonPlugin.cpp JsonParser.cpp )
set( JsonPlugin_LIBS Qt5::Script )
marble_add_plugin( JsonPlugin ${json_SRCS} )
find_package(ECM ${REQUIRED_ECM_VERSION} QUIET)
......
......@@ -17,6 +17,9 @@
#include "osm/OsmPlacemarkData.h"
#include <QIODevice>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
namespace Marble {
......@@ -45,66 +48,63 @@ bool JsonParser::read( QIODevice* device )
Q_ASSERT( m_document );
// Read file data
QString fileData = QString::fromUtf8( device->readAll() );
QJsonParseError error;
const QJsonDocument jsonDoc = QJsonDocument::fromJson(device->readAll(), &error);
// Create JSON parsing engine
// This engine evaluates and returns data from JSON
QScriptEngine m_engine;
// Store the data into JSON for better managing
m_engine.evaluate( "var fileData = " + fileData );
if (m_engine.hasUncaughtException()) {
mDebug() << "Error parsing GeoJSON : " << m_engine.uncaughtException().toString();
if (jsonDoc.isNull()) {
qDebug() << "Error parsing GeoJSON : " << error.errorString();
return false;
}
// Start parsing
const QJsonValue featuresValue = jsonDoc.object().value(QStringLiteral("features"));
// In GeoJSON format, geometries are stored in features, so we iterate on features
if ( m_engine.evaluate( "fileData.features" ).isArray() ) {
if (featuresValue.isArray()) {
const QJsonArray featureArray = featuresValue.toArray();
// Parse each feature
for ( int featureCounter = 0 ; featureCounter < m_engine.evaluate( "fileData.features.length" ).toNumber() ; featureCounter ++) {
QString count = QString::number(featureCounter);
for (int featureIndex = 0; featureIndex < featureArray.size(); ++featureIndex) {
const QJsonObject featureObject = featureArray[featureIndex].toObject();
// Check if the feature contains a geometry
if ( !m_engine.evaluate( "fileData.features[" + count + "].geometry" ).isUndefined() ) {
const QJsonValue geometryValue = featureObject.value(QStringLiteral("geometry"));
if (geometryValue.isObject()) {
const QJsonObject geometryObject = geometryValue.toObject();
// Variables for creating the geometry
QList<GeoDataGeometry*> geometryList;
QList<GeoDataPlacemark*> placemarkList;
// Create the different geometry types
const QString geometryType = geometryObject.value(QStringLiteral("type")).toString().toUpper();
if (m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == QLatin1String("POLYGON")) {
if (geometryType == QLatin1String("POLYGON")) {
// Check first that there are coordinates
if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates"));
if (coordinatesValue.isArray()) {
const QJsonArray coordinateArray = coordinatesValue.toArray();
GeoDataPolygon * geom = new GeoDataPolygon( RespectLatitudeCircle | Tessellate );
// Coordinates first array will be the outer boundary, if there are more
// positions those will be inner holes
int ringsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates.length" ).toNumber();
for ( int rings = 0 ; rings < ringsCount ; rings ++ ) {
for (int ringIndex = 0 ; ringIndex < coordinateArray.size(); ++ringIndex) {
const QJsonArray ringArray = coordinateArray[ringIndex].toArray();
QString ringCount = QString::number(rings);
GeoDataLinearRing linearRing;
int coordinatePairsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[ " + ringCount + " ].length" ).toNumber();
for( int coordinatePairs = 0 ; coordinatePairs < coordinatePairsCount ; coordinatePairs++ ) {
for (int coordinatePairIndex = 0; coordinatePairIndex < ringArray.size(); ++coordinatePairIndex) {
const QJsonArray coordinatePairArray = ringArray[coordinatePairIndex].toArray();
QString coors = QString::number(coordinatePairs);
qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + ringCount + "][" + coors + "][0]" ).toNumber();
qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + ringCount + "][" + coors + "][1]" ).toNumber();
const qreal longitude = coordinatePairArray.at(0).toDouble();
const qreal latitude = coordinatePairArray.at(1).toDouble();
linearRing.append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
}
// Outer ring
if (rings == 0) {
if (ringIndex == 0) {
geom->setOuterBoundary( linearRing );
}
// Inner holes
......@@ -115,37 +115,35 @@ bool JsonParser::read( QIODevice* device )
geometryList.append( geom );
}
} else if (m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == QLatin1String("MULTIPOLYGON")) {
} else if (geometryType == QLatin1String("MULTIPOLYGON")) {
// Check first that there are coordinates
if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates"));
if (coordinatesValue.isArray()) {
const QJsonArray coordinateArray = coordinatesValue.toArray();
int polygonsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates.length" ).toNumber();
for ( int polygons = 0 ; polygons < polygonsCount ; polygons++ ) {
for (int polygonIndex = 0; polygonIndex < coordinateArray.size(); ++polygonIndex) {
const QJsonArray polygonArray = coordinateArray[polygonIndex].toArray();
QString polygon = QString::number( polygons );
GeoDataPolygon * geom = new GeoDataPolygon( RespectLatitudeCircle | Tessellate );
// Coordinates first array will be the outer boundary, if there are more
// positions those will be inner holes
int ringsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + polygon + "].length" ).toNumber();
for ( int rings = 0 ; rings < ringsCount ; rings ++ ) {
for (int ringIndex = 0 ; ringIndex < polygonArray.size(); ++ringIndex) {
const QJsonArray ringArray = polygonArray[ringIndex].toArray();
QString ringCount = QString::number(rings);
GeoDataLinearRing linearRing;
int coordinatePairsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + polygon + "][ " + ringCount + " ].length" ).toNumber();
for( int coordinatePairs = 0 ; coordinatePairs < coordinatePairsCount ; coordinatePairs++ ) {
for (int coordinatePairIndex = 0; coordinatePairIndex < ringArray.size(); ++coordinatePairIndex) {
const QJsonArray coordinatePairArray = ringArray[coordinatePairIndex].toArray();
QString coors = QString::number(coordinatePairs);
qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + polygon + "][" + ringCount + "][" + coors + "][0]" ).toNumber();
qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + polygon + "][" + ringCount + "][" + coors + "][1]" ).toNumber();
const qreal longitude = coordinatePairArray.at(0).toDouble();
const qreal latitude = coordinatePairArray.at(1).toDouble();
linearRing.append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
}
// Outer ring
if (rings == 0) {
if (ringIndex == 0) {
geom->setOuterBoundary( linearRing );
}
// Inner holes
......@@ -157,44 +155,43 @@ bool JsonParser::read( QIODevice* device )
}
}
} else if (m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == QLatin1String("LINESTRING")) {
} else if (geometryType == QLatin1String("LINESTRING")) {
// Check first that there are coordinates
if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates"));
if (coordinatesValue.isArray()) {
const QJsonArray coordinateArray = coordinatesValue.toArray();
GeoDataLineString * geom = new GeoDataLineString( RespectLatitudeCircle | Tessellate );
int coordinatePairsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates.length" ).toNumber();
for( int coordinatePairs = 0 ; coordinatePairs < coordinatePairsCount ; coordinatePairs++ ) {
QString coors = QString::number(coordinatePairs);
for (int coordinatePairIndex = 0; coordinatePairIndex < coordinateArray.size(); ++coordinatePairIndex) {
const QJsonArray coordinatePairArray = coordinateArray[coordinatePairIndex].toArray();
qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + coors + "][0]" ).toNumber();
qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + coors + "][1]" ).toNumber();
const qreal longitude = coordinatePairArray.at(0).toDouble();
const qreal latitude = coordinatePairArray.at(1).toDouble();
geom->append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
}
geometryList.append( geom );
}
} else if (m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == QLatin1String("MULTILINESTRING")) {
} else if (geometryType == QLatin1String("MULTILINESTRING")) {
// Check first that there are coordinates
if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates"));
if (coordinatesValue.isArray()) {
const QJsonArray coordinateArray = coordinatesValue.toArray();
int linestringsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates.length" ).toNumber();
for( int linestrings = 0 ; linestrings < linestringsCount ; linestrings++ ) {
for (int lineStringIndex = 0; lineStringIndex < coordinateArray.size(); ++lineStringIndex) {
const QJsonArray lineStringArray = coordinateArray[lineStringIndex].toArray();
QString linestring = QString::number( linestrings );
GeoDataLineString * geom = new GeoDataLineString( RespectLatitudeCircle | Tessellate );
int coordinatePairsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + linestring + "].length" ).toNumber();
for( int coordinatePairs = 0 ; coordinatePairs < coordinatePairsCount ; coordinatePairs++ ) {
for (int coordinatePairIndex = 0; coordinatePairIndex < lineStringArray.size(); ++coordinatePairIndex) {
const QJsonArray coordinatePairArray = lineStringArray[coordinatePairIndex].toArray();
QString coors = QString::number(coordinatePairs);
qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + linestring + "][" + coors + "][0]" ).toNumber();
qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + linestring + "][" + coors + "][1]" ).toNumber();
const qreal longitude = coordinatePairArray.at(0).toDouble();
const qreal latitude = coordinatePairArray.at(1).toDouble();
geom->append( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
}
......@@ -202,34 +199,36 @@ bool JsonParser::read( QIODevice* device )
}
}
} else if (m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == QLatin1String("POINT")) {
} else if (geometryType == QLatin1String("POINT")) {
// Check first that there are coordinates
if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates"));
if (coordinatesValue.isArray()) {
const QJsonArray coordinatePairArray = coordinatesValue.toArray();
GeoDataPoint * geom = new GeoDataPoint();
qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[0]" ).toNumber();
qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[1]" ).toNumber();
const qreal longitude = coordinatePairArray.at(0).toDouble();
const qreal latitude = coordinatePairArray.at(1).toDouble();
geom->setCoordinates( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
geometryList.append( geom );
}
} else if (m_engine.evaluate( "fileData.features[" + count + "].geometry.type" ).toString().toUpper() == QLatin1String("MULTIPOINT")) {
} else if (geometryType == QLatin1String("MULTIPOINT")) {
// Check first that there are coordinates
if ( m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates" ).isArray() ) {
int pointsCount = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates.length" ).toNumber();
for( int points = 0 ; points < pointsCount ; points++ ) {
const QJsonValue coordinatesValue = geometryObject.value(QStringLiteral("coordinates"));
if (coordinatesValue.isArray()) {
const QJsonArray coordinateArray = coordinatesValue.toArray();
QString point = QString::number(points);
for (int pointIndex = 0; pointIndex < coordinateArray.size(); ++pointIndex) {
const QJsonArray coordinatePairArray = coordinateArray[pointIndex].toArray();
GeoDataPoint * geom = new GeoDataPoint();
qreal longitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + point + "][0]" ).toNumber();
qreal latitude = m_engine.evaluate( "fileData.features[" + count + "].geometry.coordinates[" + point + "][1]" ).toNumber();
const qreal longitude = coordinatePairArray.at(0).toDouble();
const qreal latitude = coordinatePairArray.at(1).toDouble();
geom->setCoordinates( GeoDataCoordinates( longitude , latitude , 0 , GeoDataCoordinates::Degree ) );
......@@ -240,10 +239,9 @@ bool JsonParser::read( QIODevice* device )
// Parse the features properties
if ( !geometryList.isEmpty() != 0 && !m_engine.evaluate( "fileData.features[" + count + "].properties" ).isUndefined() ) {
QScriptValue properties = m_engine.evaluate( "fileData.features[" + count + "].properties" );
QScriptValueIterator propertyIterator ( properties );
const QJsonValue propertiesValue = featureObject.value(QStringLiteral("properties"));
if (!geometryList.isEmpty() && propertiesValue.isObject()) {
const QJsonObject propertiesObject = propertiesValue.toObject();
// First create a placemark for each geometry, there could be multi geometries
// that are translated into more than one geometry/placemark
......@@ -253,9 +251,17 @@ bool JsonParser::read( QIODevice* device )
}
OsmPlacemarkData osmData;
while ( propertyIterator.hasNext() ) {
propertyIterator.next();
osmData.addTag(propertyIterator.name(), propertyIterator.value().toString());
QJsonObject::ConstIterator it = propertiesObject.begin();
const QJsonObject::ConstIterator end = propertiesObject.end();
for ( ; it != end; ++it) {
if (it.value().isObject() || it.value().isArray()) {
qDebug() << "Skipping property, values of type arrays and objects not supported:" << it.key();
continue;
}
// pass value through QVariant to also get bool & numbers
osmData.addTag(it.key(), it.value().toVariant().toString());
}
// If the property read, is the features name
......
......@@ -13,10 +13,6 @@
#include "GeoDataDocument.h"
#include <QScriptEngine>
#include <QScriptValue>
#include <QScriptValueIterator>
class QIODevice;
namespace Marble {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment