Skip to content

Commit

Permalink
Merge pull request #2617 from SebDieBln/FixLayerDefVectorJoins
Browse files Browse the repository at this point in the history
Make vector joins work within layer-definition-files
  • Loading branch information
Hugo Mercier committed Jan 6, 2016
2 parents 946f4e4 + c136f9f commit b46a593
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 13 deletions.
2 changes: 2 additions & 0 deletions python/core/qgslayerdefinition.sip
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ class QgsLayerDefinition
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage /Out/ );
/** Export the selected layer tree nodes to a QLR file */
static bool exportLayerDefinition( QString path, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage /Out/ );
/** Export the selected layer tree nodes to a QLR-XML document */
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString::null );
};

57 changes: 44 additions & 13 deletions src/core/qgslayerdefinition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "qgslogger.h"
#include "qgsmaplayer.h"
#include "qgsvectorlayer.h"
#include "qgslayertree.h"
#include "qgsmaplayerregistry.h"
#include "qgslayerdefinition.h"
Expand Down Expand Up @@ -62,6 +63,18 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGrou
layerNode.toElement().setAttribute( "id", newid );
}
}

// change layer IDs for vector joins
QDomNodeList vectorJoinNodes = doc.elementsByTagName( "join" ); // TODO: Find a better way of searching for vectorjoins, there might be other <join> elements within the project.
for ( int j = 0; j < vectorJoinNodes.size(); ++j )
{
QDomNode joinNode = vectorJoinNodes.at( j );
QDomElement joinElement = joinNode.toElement();
if ( joinElement.attribute( "joinLayerId" ) == oldid )
{
joinNode.toElement().setAttribute( "joinLayerId", newid );
}
}
}

QDomElement layerTreeElem = doc.documentElement().firstChildElement( "layer-tree-group" );
Expand All @@ -75,6 +88,17 @@ bool QgsLayerDefinition::loadLayerDefinition( QDomDocument doc, QgsLayerTreeGrou
QList<QgsMapLayer*> layers = QgsMapLayer::fromLayerDefinition( doc );
QgsMapLayerRegistry::instance()->addMapLayers( layers, loadInLegend );

// Now that all layers are loaded, refresh the vectorjoins to get the joined fields
Q_FOREACH ( QgsMapLayer* layer, layers )
{
QgsVectorLayer* vlayer = static_cast< QgsVectorLayer * >( layer );
if ( vlayer )
{
vlayer->createJoinCaches();
vlayer->updateFields();
}
}

QList<QgsLayerTreeNode*> nodes = root->children();
Q_FOREACH ( QgsLayerTreeNode *node, nodes )
root->takeChild( node );
Expand All @@ -95,6 +119,24 @@ bool QgsLayerDefinition::exportLayerDefinition( QString path, const QList<QgsLay
QFileInfo fileinfo( file );

QDomDocument doc( "qgis-layer-definition" );
if ( !exportLayerDefinition( doc, selectedTreeNodes, errorMessage, fileinfo.canonicalFilePath() ) )
return false;
if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
{
QTextStream qlayerstream( &file );
doc.save( qlayerstream, 2 );
return true;
}
else
{
errorMessage = file.errorString();
return false;
}
}

bool QgsLayerDefinition::exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath )
{
Q_UNUSED( errorMessage );
QDomElement qgiselm = doc.createElement( "qlr" );
doc.appendChild( qgiselm );
QList<QgsLayerTreeNode*> nodes = selectedTreeNodes;
Expand All @@ -111,20 +153,9 @@ bool QgsLayerDefinition::exportLayerDefinition( QString path, const QList<QgsLay
Q_FOREACH ( QgsLayerTreeLayer* layer, layers )
{
QDomElement layerelm = doc.createElement( "maplayer" );
layer->layer()->writeLayerXML( layerelm, doc, fileinfo.canonicalFilePath() );
layer->layer()->writeLayerXML( layerelm, doc, relativeBasePath );
layerselm.appendChild( layerelm );
}
qgiselm.appendChild( layerselm );

if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
{
QTextStream qlayerstream( &file );
doc.save( qlayerstream, 2 );
return true;
}
else
{
errorMessage = file.errorString();
return false;
}
return true;
}
2 changes: 2 additions & 0 deletions src/core/qgslayerdefinition.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class CORE_EXPORT QgsLayerDefinition
static bool loadLayerDefinition( QDomDocument doc, QgsLayerTreeGroup* rootGroup, QString &errorMessage );
/** Export the selected layer tree nodes to a QLR file */
static bool exportLayerDefinition( QString path, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage );
/** Export the selected layer tree nodes to a QLR-XML document */
static bool exportLayerDefinition( QDomDocument doc, const QList<QgsLayerTreeNode*>& selectedTreeNodes, QString &errorMessage, const QString& relativeBasePath = QString::null );
};

#endif // QGSLAYERDEFINITION_H
55 changes: 55 additions & 0 deletions tests/src/core/testqgsvectorlayerjoinbuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
#include <qgsapplication.h>
#include <qgsvectorlayerjoinbuffer.h>
#include <qgsmaplayerregistry.h>
#include <qgslayerdefinition.h>
#include <qgsproject.h>

/** @ingroup UnitTests
* This is a unit test for the vector layer join buffer
Expand Down Expand Up @@ -53,6 +55,7 @@ class TestVectorLayerJoinBuffer : public QObject
void testJoinSubset_data();
void testJoinSubset();
void testJoinTwoTimes();
void testJoinLayerDefinitionFile();

private:
QgsVectorLayer* mLayerA;
Expand Down Expand Up @@ -339,6 +342,58 @@ void TestVectorLayerJoinBuffer::testJoinTwoTimes()
QCOMPARE( mLayerA->vectorJoins().count(), 0 );
}

void TestVectorLayerJoinBuffer::testJoinLayerDefinitionFile()
{
bool r;

QgsMapLayerRegistry::instance()->removeAllMapLayers();

// Create two layers
QgsVectorLayer* layerA = new QgsVectorLayer( "Point?crs=epsg:4326&field=key:integer&field=value:double&index=yes", "layerA", "memory" );
QVERIFY( layerA );
QgsMapLayerRegistry::instance()->addMapLayer( layerA );

QgsVectorLayer* layerB = new QgsVectorLayer( "Point?crs=epsg:4326&field=id:integer&index=yes", "layerB", "memory" );
QVERIFY( layerB );
QgsMapLayerRegistry::instance()->addMapLayer( layerB );

// Create vector join
QgsVectorJoinInfo joinInfo;
joinInfo.targetFieldName = "id";
joinInfo.joinLayerId = layerA->id();
joinInfo.joinFieldName = "key";
joinInfo.memoryCache = true;
joinInfo.prefix = "joined_";
r = layerB->addJoin( joinInfo );
QVERIFY( r );

// Generate QLR
QDomDocument qlrDoc( "qgis-layer-definition" );
QString errorMessage;
r = QgsLayerDefinition::exportLayerDefinition( qlrDoc, QgsProject::instance()->layerTreeRoot()->children(), errorMessage );
QVERIFY2( r, errorMessage.toUtf8().constData() );

// Clear
QgsMapLayerRegistry::instance()->removeAllMapLayers();

// Load QLR
r = QgsLayerDefinition::loadLayerDefinition( qlrDoc, QgsProject::instance()->layerTreeRoot(), errorMessage );
QVERIFY2( r, errorMessage.toUtf8().constData() );

// Get layer
QList<QgsMapLayer*> mapLayers = QgsMapLayerRegistry::instance()->mapLayersByName( "layerB" );
QCOMPARE( mapLayers.count(), 1 );

QgsVectorLayer* vLayer = static_cast<QgsVectorLayer*>( mapLayers.value( 0 ) );
QVERIFY( vLayer );

// Check for vector join
QCOMPARE( vLayer->vectorJoins().count(), 1 );

// Check for joined field
QVERIFY( vLayer->fieldNameIndex( joinInfo.prefix + "value" ) >= 0 );
}


QTEST_MAIN( TestVectorLayerJoinBuffer )
#include "testqgsvectorlayerjoinbuffer.moc"
Expand Down

0 comments on commit b46a593

Please sign in to comment.