Skip to content
Permalink
Browse files

Rework vector joins so they do not use QgsProject::instance()

The basic idea is to split reading of XML definition and resolution of layer IDs into layers.

Also includes some cleanups in QgsProject and improvements in QgsVectorLayerJoinInfo.
  • Loading branch information
wonder-sk committed Jan 31, 2017
1 parent 2a518fd commit 7683cfacd347a95d9a2168e1efa239966ff8ddf7
@@ -179,6 +179,7 @@ Renamed Classes {#qgis_api_break_3_0_renamed_classes}
<tr><td>QgsVectorGradientColorRampV2Dialog<td>QgsGradientColorRampDialog
<tr><td>QgsVectorGradientColorRampV2DialogBase<td>QgsGradientColorRampDialogBase
<tr><td>QgsVectorGradientRampV2<td>QgsVectorGradientRamp
<tr><td>QgsVectorJoinInfo<td>QgsVectorLayerJoinInfo
<tr><td>QgsVectorLayersetRendererV2<td>QgsVectorLayersetRenderer
<tr><td>QgsVectorRandomColorRampV2<td>QgsLimitedRandomColorRamp
<tr><td>QgsVectorRandomColorRampV2Dialog<td>QgsLimitedRandomColorRampDialog
@@ -1531,6 +1532,7 @@ QgsProject {#qgis_api_break_3_0_QgsProject}
- read( QDomNode& layerNode ) was renamed to readLayer( const QDomNode& layerNode ).
- read( const QFileInfo& file ) was replaced by read( const QString& filename ).
- write( const QFileInfo& file ) was replaced by write( const QString& filename ).
- createEmbeddedLayer() does not take vectorLayerList as the third parameter anymore.


QgsProjectPropertyValue {#qgis_api_break_3_0_QgsProjectPropertyValue}
@@ -1887,6 +1889,13 @@ QGIS 3.0 defaultValue() only returns literal, constant defaultValues. A new meth
has been added which returns the SQL clause fragments which must be evaluated by the provider itself.


QgsVectorJoinInfo {#qgis_api_break_3_0_QgsVectorJoinInfo}
-----------------

- class has been renamed to QgsVectorLayerJoinInfo
- member variables are now accessible through pairs of getters and setters rather than using direct read/write


QgsVectorLayer {#qgis_api_break_3_0_QgsVectorLayer}
--------------

@@ -1926,6 +1935,9 @@ displayExpression instead. For the map tip use mapTipTemplate() instead.
- loadNamedStyle(): theResultFlag argument is correctly declared as output argument
- The duplicate selectionChanged() signal was removed. Use selectionChanged( const QgsFeatureIds&, const QgsFeatureIds&, const bool ) instead.
- featureCount() now requires a legend key string instead of a QgsSymbol pointer argument.
- createJoinCaches() has been removed. Caches are created/updated when needed internally.
- checkJoinLayerRemove() has been removed. Joins are removed internally when joined layer is deleted.
- readXml() does not resolve references to joined layers. Call resolveReferences() when joined layers are available.

QgsVectorLayerEditBuffer {#qgis_api_break_3_0_QgsVectorLayerEditBuffer}
------------------------
@@ -1953,6 +1965,12 @@ in code which previously passed a null pointer to QgsVectorLayerImport.
- ErrUserCancelled (ImportError enum value) has been renamed to ErrUserCanceled <!--#spellok-->


QgsVectorLayerJoinBuffer {#qgis_api_break_3_0_QgsVectorLayerJoinBuffer}
------------------------

- readXml() does not resolve layer IDs to layers anymore. You need to call resolveReferences() afterwards.


QgsVectorLayerUndoCommand {#qgis_api_break_3_0_QgsVectorLayerUndoCommand}
-------------------------

@@ -155,6 +155,7 @@
%Include qgsvectorlayereditpassthrough.sip
%Include qgsvectorlayerimport.sip
%Include qgsvectorlayerjoinbuffer.sip
%Include qgsvectorlayerjoininfo.sip
%Include qgsvectorlayertools.sip
%Include qgsvectorlayerundocommand.sip
%Include qgsvectorlayerutils.sip
@@ -3,46 +3,6 @@ typedef QList<int> QgsAttributeList;
typedef QSet<int> QgsAttributeIds;


struct QgsVectorJoinInfo
{
%TypeHeaderCode
#include "qgsvectorlayer.h"
%End
QgsVectorJoinInfo();

/** Join field in the target layer*/
QString targetFieldName;
/** Source layer*/
QString joinLayerId;
/** Join field in the source layer*/
QString joinFieldName;
/** True if the join is cached in virtual memory*/
bool memoryCache;
/** True if the cached join attributes need to be updated*/
bool cacheDirty;

/** Cache for joined attributes to provide fast lookup (size is 0 if no memory caching)
* @note not available in python bindings
*/
// QHash< QString, QgsAttributeMap> cachedAttributes;

/** An optional prefix. If it is a Null string "{layername}_" will be used
* @note Added in 2.8
*/
QString prefix;

bool operator==( const QgsVectorJoinInfo& other ) const;

/** Set subset of fields to be used from joined layer. Takes ownership of the passed pointer. Null pointer tells to use all fields.
@note added in 2.6 */
void setJoinFieldNamesSubset( QStringList* fieldNamesSubset /Transfer/ );
/** Get subset of fields to be used from joined layer. All fields will be used if null is returned.
@note added in 2.6 */
QStringList* joinFieldNamesSubset() const;
};



/** \ingroup core
* Represents a vector layer which manages a vector based data sets.
*
@@ -413,7 +373,7 @@ class QgsVectorLayer : QgsMapLayer, QgsExpressionContextGenerator
/** Joins another vector layer to this layer
@param joinInfo join object containing join layer id, target and source field
@note since 2.6 returns bool indicating whether the join can be added */
bool addJoin( const QgsVectorJoinInfo& joinInfo );
bool addJoin( const QgsVectorLayerJoinInfo& joinInfo );

/** Removes a vector layer join
@returns true if join was found and successfully removed */
@@ -424,7 +384,7 @@ class QgsVectorLayer : QgsMapLayer, QgsExpressionContextGenerator
* @note added 2.14.7
*/
QgsVectorLayerJoinBuffer* joinBuffer();
const QList<QgsVectorJoinInfo> vectorJoins() const;
const QList<QgsVectorLayerJoinInfo> vectorJoins() const;

/**
* Sets the list of dependencies.
@@ -656,6 +616,11 @@ class QgsVectorLayer : QgsMapLayer, QgsExpressionContextGenerator
*/
virtual bool writeXml( QDomNode & layer_node, QDomDocument & doc ) const;

/** Resolve references to other layers (kept as layer IDs after reading XML) into layer objects.
* @note added in 3.0
*/
void resolveReferences( QgsProject* project );

/**
* Save named and sld style of the layer to the style table in the db.
* @param name
@@ -1216,10 +1181,6 @@ class QgsVectorLayer : QgsMapLayer, QgsExpressionContextGenerator
/** Assembles mUpdatedFields considering provider fields, joined fields and added fields */
void updateFields();

/** Caches joined attributes if required (and not already done) */
// marked as const as these are just caches, and need to be created from const accessors
void createJoinCaches() const;

/** Returns the calculated default value for the specified field index. The default
* value may be taken from a client side default value expression (see setDefaultValueExpression())
* or taken from the underlying data provider.
@@ -1539,9 +1500,6 @@ class QgsVectorLayer : QgsMapLayer, QgsExpressionContextGenerator
*/
virtual void updateExtents();

/** Check if there is a join with a layer that will be removed */
void checkJoinLayerRemove( const QString& theLayerId );

/**
* Make layer editable.
* This starts an edit session on this layer. Changes made in this edit session will not
@@ -10,7 +10,7 @@ class QgsVectorLayerJoinBuffer : QObject
/** Joins another vector layer to this layer
@param joinInfo join object containing join layer id, target and source field
@return (since 2.6) whether the join was successfully added */
bool addJoin( const QgsVectorJoinInfo& joinInfo );
bool addJoin( const QgsVectorLayerJoinInfo& joinInfo );

/** Removes a vector layer join
@returns true if join was found and successfully removed */
@@ -30,20 +30,24 @@ class QgsVectorLayerJoinBuffer : QObject
/** Reads joins from project file*/
void readXml( const QDomNode& layer_node );

//! Resolves layer IDs of joined layers using given project's available layers
//! @note added in 3.0
void resolveReferences( QgsProject* project );

/** Quick way to test if there is any join at all*/
bool containsJoins() const;

const QList< QgsVectorJoinInfo >& vectorJoins() const;
const QList< QgsVectorLayerJoinInfo >& vectorJoins() const;

/** Finds the vector join for a layer field index.
@param index this layers attribute index
@param fields fields of the vector layer (including joined fields)
@param sourceFieldIndex Output: field's index in source layer */
const QgsVectorJoinInfo* joinForFieldIndex( int index, const QgsFields& fields, int& sourceFieldIndex /Out/ ) const;
const QgsVectorLayerJoinInfo* joinForFieldIndex( int index, const QgsFields& fields, int& sourceFieldIndex /Out/ ) const;

//! Find out what is the first index of the join within fields. Returns -1 if join is not present
//! @note added in 2.6
int joinedFieldsOffset( const QgsVectorJoinInfo* info, const QgsFields& fields );
int joinedFieldsOffset( const QgsVectorLayerJoinInfo* info, const QgsFields& fields );

//! Return a vector of indices for use in join based on field names from the layer
//! @note added in 2.6
@@ -0,0 +1,49 @@

class QgsVectorLayerJoinInfo
{
%TypeHeaderCode
#include "qgsvectorlayerjoininfo.h"
%End

public:
QgsVectorLayerJoinInfo();

//! Sets weak reference to the joined layer
void setJoinLayer( QgsVectorLayer* layer );
//! Returns joined layer (may be null if the reference was set by layer ID and not resolved yet)
QgsVectorLayer* joinLayer() const;

//! Sets ID of the joined layer. It will need to be overwritten by setJoinLayer() to a reference to real layer
void setJoinLayerId( const QString& layerId );
//! ID of the joined layer - may be used to resolve reference to the joined layer
QString joinLayerId() const;

//! Sets name of the field of our layer that will be used for join
void setTargetFieldName( const QString& fieldName );
//! Returns name of the field of our layer that will be used for join
QString targetFieldName() const;

//! Sets name of the field of joined layer that will be used for join
void setJoinFieldName( const QString& fieldName );
//! Returns name of the field of joined layer that will be used for join
QString joinFieldName() const;

//! Sets prefix of fields from the joined layer. If null, joined layer's name will be used.
void setPrefix( const QString& prefix );
//! Returns prefix of fields from the joined layer. If null, joined layer's name will be used.
QString prefix() const;

//! Sets whether values from the joined layer should be cached in memory to speed up lookups
void setUsingMemoryCache( bool enabled );
//! Returns whether values from the joined layer should be cached in memory to speed up lookups
bool isUsingMemoryCache() const;

bool operator==( const QgsVectorLayerJoinInfo& other ) const;

/** Set subset of fields to be used from joined layer. Takes ownership of the passed pointer. Null pointer tells to use all fields.
@note added in 2.6 */
void setJoinFieldNamesSubset( QStringList* fieldNamesSubset /Transfer/ );
/** Get subset of fields to be used from joined layer. All fields will be used if null is returned.
@note added in 2.6 */
QStringList* joinFieldNamesSubset() const;
};
@@ -247,6 +247,7 @@
#include "qgsvirtuallayerdefinitionutils.h"
#include "qgstransaction.h"
#include "qgstransactiongroup.h"
#include "qgsvectorlayerjoininfo.h"
#include "qgsvectorlayerutils.h"
#include "qgshelp.h"

@@ -8543,7 +8544,7 @@ void QgisApp::duplicateLayers( const QList<QgsMapLayer *>& lyrList )
QgsExpressionContextUtils::setLayerVariable( dupVLayer, variableName, varValue );
}

Q_FOREACH ( const QgsVectorJoinInfo& join, vlayer->vectorJoins() )
Q_FOREACH ( const QgsVectorLayerJoinInfo& join, vlayer->vectorJoins() )
dupVLayer->addJoin( join );

for ( int fld = 0; fld < vlayer->fields().count(); fld++ )
@@ -9509,7 +9510,6 @@ void QgisApp::embedLayers()

//layer ids
QList<QDomNode> brokenNodes;
QList< QPair< QgsVectorLayer*, QDomElement > > vectorLayerList;

// resolve dependencies
QgsLayerDefinition::DependencySorter depSorter( projectFile );
@@ -9520,7 +9520,7 @@ void QgisApp::embedLayers()
Q_FOREACH ( const QString& selId, layerIds )
{
if ( selId == id )
QgsProject::instance()->createEmbeddedLayer( selId, projectFile, brokenNodes, vectorLayerList );
QgsProject::instance()->createEmbeddedLayer( selId, projectFile, brokenNodes );
}
}

@@ -20,6 +20,7 @@
#include "qgsproject.h"
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayerjoininfo.h"
#include "qgsmaplayercombobox.h"
#include "qgsfieldcombobox.h"

@@ -66,20 +67,20 @@ QgsJoinDialog::~QgsJoinDialog()
{
}

void QgsJoinDialog::setJoinInfo( const QgsVectorJoinInfo& joinInfo )
void QgsJoinDialog::setJoinInfo( const QgsVectorLayerJoinInfo& joinInfo )
{
mJoinLayerComboBox->setLayer( QgsProject::instance()->mapLayer( joinInfo.joinLayerId ) );
mJoinFieldComboBox->setField( joinInfo.joinFieldName );
mTargetFieldComboBox->setField( joinInfo.targetFieldName );
mCacheInMemoryCheckBox->setChecked( joinInfo.memoryCache );
if ( joinInfo.prefix.isNull() )
mJoinLayerComboBox->setLayer( joinInfo.joinLayer() );
mJoinFieldComboBox->setField( joinInfo.joinFieldName() );
mTargetFieldComboBox->setField( joinInfo.targetFieldName() );
mCacheInMemoryCheckBox->setChecked( joinInfo.isUsingMemoryCache() );
if ( joinInfo.prefix().isNull() )
{
mUseCustomPrefix->setChecked( false );
}
else
{
mUseCustomPrefix->setChecked( true );
mCustomPrefix->setText( joinInfo.prefix );
mCustomPrefix->setText( joinInfo.prefix() );
}

QStringList* lst = joinInfo.joinFieldNamesSubset();
@@ -102,21 +103,18 @@ void QgsJoinDialog::setJoinInfo( const QgsVectorJoinInfo& joinInfo )
}
}

QgsVectorJoinInfo QgsJoinDialog::joinInfo() const
QgsVectorLayerJoinInfo QgsJoinDialog::joinInfo() const
{
QgsVectorJoinInfo info;
if ( mJoinLayerComboBox->currentLayer() )
info.joinLayerId = mJoinLayerComboBox->currentLayer()->id();
info.joinFieldName = mJoinFieldComboBox->currentField();
info.targetFieldName = mTargetFieldComboBox->currentField();
info.memoryCache = mCacheInMemoryCheckBox->isChecked();
info.targetFieldIndex = -1;
info.joinFieldIndex = -1;
QgsVectorLayerJoinInfo info;
info.setJoinLayer( qobject_cast<QgsVectorLayer*>( mJoinLayerComboBox->currentLayer() ) );
info.setJoinFieldName( mJoinFieldComboBox->currentField() );
info.setTargetFieldName( mTargetFieldComboBox->currentField() );
info.setUsingMemoryCache( mCacheInMemoryCheckBox->isChecked() );

if ( mUseCustomPrefix->isChecked() )
info.prefix = mCustomPrefix->text();
info.setPrefix( mCustomPrefix->text() );
else
info.prefix = QString::null;
info.setPrefix( QString::null );

if ( mUseJoinFieldsSubset->isChecked() )
{
@@ -22,7 +22,7 @@
#include "qgis_app.h"

class QgsVectorLayer;
struct QgsVectorJoinInfo;
class QgsVectorLayerJoinInfo;

class APP_EXPORT QgsJoinDialog: public QDialog, private Ui::QgsJoinDialogBase
{
@@ -32,10 +32,10 @@ class APP_EXPORT QgsJoinDialog: public QDialog, private Ui::QgsJoinDialogBase
~QgsJoinDialog();

//! Configure the dialog for an existing join
void setJoinInfo( const QgsVectorJoinInfo& joinInfo );
void setJoinInfo( const QgsVectorLayerJoinInfo& joinInfo );

//! Returns the join info
QgsVectorJoinInfo joinInfo() const;
QgsVectorLayerJoinInfo joinInfo() const;

//! Returns true if user wants to create an attribute index on the join field
bool createAttributeIndex() const;

0 comments on commit 7683cfa

Please sign in to comment.
You can’t perform that action at this time.