Skip to content

Commit

Permalink
QgsVectorLayer: large internal refactoring
Browse files Browse the repository at this point in the history
Most important changes:
- introduced feature iterator for QgsVectorLayer
- vector editing moved to QgsVectorEditBuffer
- complete rework of undo/redo commands for vector layers
- geometry cache separated from editing (QgsVectorLayerCache)
- non-essential editing functionality moved to QgsVectorLayerEditUtils
  • Loading branch information
wonder-sk committed Dec 17, 2012
1 parent 7ed9308 commit 81b0930
Show file tree
Hide file tree
Showing 50 changed files with 4,082 additions and 2,473 deletions.
1 change: 1 addition & 0 deletions python/core/core.sip
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
%Include qgsvectordataprovider.sip
%Include qgsvectorfilewriter.sip
%Include qgsvectorlayer.sip
%Include qgsvectorlayereditbuffer.sip
%Include qgsvectorlayerimport.sip
%Include qgsvectorlayerjoinbuffer.sip
%Include qgsvectorlayerundocommand.sip
Expand Down
1 change: 0 additions & 1 deletion python/core/qgsfeature.sip
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ typedef QMap<int, QString> QgsFieldNameMap;
typedef QList<QgsFeature> QgsFeatureList;

typedef QMap<int, QgsField> QgsFieldMap;
typedef QVector<QgsField> QgsFields;

class QgsFeature
{
Expand Down
66 changes: 66 additions & 0 deletions python/core/qgsfield.sip
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public:
~QgsField();

bool operator==( const QgsField& other ) const;
bool operator!=( const QgsField& other ) const;

//! Gets the name of the field
const QString & name() const;
Expand Down Expand Up @@ -108,3 +109,68 @@ public:
void setComment( const QString & comment );

}; // class QgsField



class QgsFields
{
%TypeHeaderCode
#include <qgsfield.h>
%End

public:

enum FieldOrigin { OriginUnknown, OriginProvider, OriginJoin, OriginEdit };

void clear();
void append( const QgsField& field, FieldOrigin origin = OriginProvider, int originIndex = -1 );
void remove( int fieldIdx );

bool isEmpty() const;
int count() const /__len__/;
int size() const;
//const QgsField& operator[](int i) const;
//QgsField& operator[](int i);
const QgsField& at(int i) const;
QList<QgsField> toList() const;

const QgsField& field( int fieldIdx ) const;
const QgsField& field( const QString& name ) const;
FieldOrigin fieldOrigin( int fieldIdx ) const;
int fieldOriginIndex( int fieldIdx ) const;

int indexFromName( const QString& name ) const;


QgsField& operator[](int i);
%MethodCode
int idx = (int)sipConvertFromSequenceIndex(a0, sipCpp->count());
if (idx < 0)
sipIsErr = 1;
else
sipRes = new QgsField(sipCpp->operator[](idx));
%End

/* SIP_PYOBJECT __getitem__(int key);
%MethodCode
if (a0 = sipConvertFromSequenceIndex(a0, sipCpp->count()) < 0)
sipIsErr = 1;
else
{
qDebug("__getitem__ %d", a0);
QgsField* fld = new QgsField(sipCpp->at(a0));
sipRes = sipConvertFromInstance(fld, sipClass_QgsField, Py_None);
}
%End*/

void __setitem__(int key, const QgsField& field);
%MethodCode
int idx = (int)sipConvertFromSequenceIndex(a0, sipCpp->count());
if (idx < 0)
sipIsErr = 1;
else
(*sipCpp)[idx] = *a1;
%End

};

8 changes: 8 additions & 0 deletions python/core/qgsvectordataprovider.sip
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,14 @@ class QgsVectorDataProvider : QgsDataProvider
struct NativeType
{
NativeType( QString typeDesc, QString typeName, QVariant::Type type, int minLen = 0, int maxLen = 0, int minPrec = 0, int maxPrec = 0 );

QString mTypeDesc;
QString mTypeName;
QVariant::Type mType;
int mMinLen;
int mMaxLen;
int mMinPrec;
int mMaxPrec;
};

/**
Expand Down
23 changes: 12 additions & 11 deletions python/core/qgsvectorlayer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ struct QgsVectorJoinInfo
%End

/**Join field in the target layer*/
int targetField;
QString targetFieldName;
/**Source layer*/
QString joinLayerId;
/**Join field in the source layer*/
int joinField;
QString joinFieldName;
/**True if the join is cached in virtual memory*/
bool memoryCache;
/**Cache for joined attributes to provide fast lookup (size is 0 if no memory caching)
Expand Down Expand Up @@ -302,6 +302,11 @@ class QgsVectorLayer : QgsMapLayer
bool fetchGeometry = true,
bool useIntersect = false );

/**
* Query the provider for features specified in request.
*/
QgsFeatureIterator getFeatures( const QgsFeatureRequest& request = QgsFeatureRequest() );

/**
* fetch a feature (after select)
* @param feature buffer to read the feature into
Expand Down Expand Up @@ -484,9 +489,6 @@ class QgsVectorLayer : QgsMapLayer
*/
bool setReadOnly( bool readonly = true );

/** Sets whether some features are modified or not */
void setModified( bool modified = true, bool onlyGeometryWasModified = false );

/** Make layer editable */
bool startEditing();

Expand Down Expand Up @@ -614,6 +616,9 @@ class QgsVectorLayer : QgsMapLayer
QgsVectorOverlay* findOverlayByType( const QString& typeName );


//! Buffer with uncommitted editing operations. Only valid after editing has been turned on.
QgsVectorLayerEditBuffer* editBuffer();

/**
* Create edit command for undo/redo operations
* @param text text which is to be displayed in undo window
Expand Down Expand Up @@ -654,10 +659,6 @@ class QgsVectorLayer : QgsMapLayer
@note public and static from version 1.4 */
static void drawVertexMarker( double x, double y, QPainter& p, QgsVectorLayer::VertexMarkerType type, int vertexSize );

/** Assembles mUpdatedFields considering provider fields, joined fields and added fields
@note added in 1.7 */
void updateFieldMap();

/** Caches joined attributes if required (and not already done)
@note added in 1.7 */
void createJoinCaches();
Expand Down Expand Up @@ -706,7 +707,7 @@ class QgsVectorLayer : QgsMapLayer
void selectionChanged();

/** This signal is emitted when modifications has been done on layer */
void layerModified( bool onlyGeometry );
void layerModified();

void editingStarted();
void editingStopped();
Expand All @@ -721,7 +722,7 @@ class QgsVectorLayer : QgsMapLayer

/** Signals emitted after committing changes
\note added in v1.6 */
void committedAttributesDeleted( const QString& layerId, const QgsAttributeIds& deletedAttributeIds );
void committedAttributesDeleted( const QString& layerId, const QgsAttributeList& deletedAttributeIds );
void committedAttributesAdded( const QString& layerId, const QList<QgsField>& addedAttributes );
void committedFeaturesAdded( const QString& layerId, const QgsFeatureList& addedFeatures );
void committedFeaturesRemoved( const QString& layerId, const QgsFeatureIds& deletedFeatureIds );
Expand Down
104 changes: 104 additions & 0 deletions python/core/qgsvectorlayereditbuffer.sip
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@


class QgsVectorLayerEditBuffer : QObject
{
%TypeHeaderCode
#include "qgsvectorlayereditbuffer.h"
%End

public:
QgsVectorLayerEditBuffer(QgsVectorLayer* layer);
~QgsVectorLayerEditBuffer();

/** Returns true if the provider has been modified since the last commit */
bool isModified() const;


/** Adds a feature
@param f feature to add
@param alsoUpdateExtent If True, will also go to the effort of e.g. updating the extents.
@return True in case of success and False in case of error
*/
bool addFeature( QgsFeature& f );

/** Insert a copy of the given features into the layer (but does not commit it) */
bool addFeatures( QgsFeatureList& features );

/** delete a feature from the layer (but does not commit it) */
bool deleteFeature( QgsFeatureId fid );

/** change feature's geometry
@note added in version 1.2 */
bool changeGeometry( QgsFeatureId fid, QgsGeometry* geom );

/** changed an attribute value (but does not commit it) */
bool changeAttributeValue( QgsFeatureId fid, int field, QVariant value );

/** add an attribute field (but does not commit it)
returns true if the field was added
@note added in version 1.2 */
bool addAttribute( const QgsField &field );

/** delete an attribute field (but does not commit it) */
bool deleteAttribute( int attr );


/**
Attempts to commit any changes to disk. Returns the result of the attempt.
If a commit fails, the in-memory changes are left alone.

This allows editing to continue if the commit failed on e.g. a
disallowed value in a Postgres database - the user can re-edit and try
again.

The commits occur in distinct stages,
(add attributes, add features, change attribute values, change
geometries, delete features, delete attributes)
so if a stage fails, it's difficult to roll back cleanly.
Therefore any error message also includes which stage failed so
that the user has some chance of repairing the damage cleanly.
*/
bool commitChanges(QStringList& commitErrors);

/** Stop editing and discard the edits */
void rollBack();


/** New features which are not commited. */
const QgsFeatureList& addedFeatures();

/** Changed attributes values which are not commited */
const QgsChangedAttributesMap& changedAttributeValues();

/** deleted attributes fields which are not commited. The list is kept sorted. */
const QgsAttributeList& deletedAttributeIds();

/** added attributes fields which are not commited */
const QList<QgsField>& addedAttributes();

/** Changed geometries which are not commited. */
const QgsGeometryMap& changedGeometries();

//QString dumpEditBuffer();

signals:
/** This signal is emitted when modifications has been done on layer */
void layerModified( bool onlyGeometry );

void featureAdded( QgsFeatureId fid );
void featureDeleted( QgsFeatureId fid );
void geometryChanged( QgsFeatureId fid, QgsGeometry &geom );
void attributeValueChanged( QgsFeatureId fid, int idx, const QVariant & );
void attributeAdded( int idx );
void attributeDeleted( int idx );

/** Signals emitted after committing changes
\note added in v1.6 */
void committedAttributesDeleted( const QString& layerId, const QgsAttributeList& deletedAttributes );
void committedAttributesAdded( const QString& layerId, const QList<QgsField>& addedAttributes );
void committedFeaturesAdded( const QString& layerId, const QgsFeatureList& addedFeatures );
void committedFeaturesRemoved( const QString& layerId, const QgsFeatureIds& deletedFeatureIds );
void committedAttributeValuesChanges( const QString& layerId, const QgsChangedAttributesMap& changedAttributesValues );
void committedGeometriesChanges( const QString& layerId, const QgsGeometryMap& changedGeometries );

};
16 changes: 3 additions & 13 deletions python/core/qgsvectorlayerjoinbuffer.sip
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,11 @@ class QgsVectorLayerJoinBuffer
/**Removes a vector layer join*/
void removeJoin( const QString& joinLayerId );

/**Creates QgsVectorLayerJoinBuffer for the joins containing attributes to fetch*/
void select( const QgsAttributeList& fetchAttributes,
QgsAttributeList& sourceJoinFields, int providerFieldCount );

/**Updates field map with joined attributes
@param fields map to append joined attributes
*/
void updateFields( QgsFields& fields );

/**Update feature with uncommited attribute updates and joined attributes*/
void updateFeatureAttributes( QgsFeature &f, int providerFieldCount, bool all = false );

/**Calls cacheJoinLayer() for all vector joins*/
void createJoinCaches();

Expand All @@ -37,16 +30,13 @@ class QgsVectorLayerJoinBuffer

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

const QList< QgsVectorJoinInfo >& vectorJoins() const;

/**Finds the vector join for a layer field index.
@param index this layers attribute index
@param maxProviderIndex maximum attribute index of the vectorlayer provider
@param indexOffset out: offset between layer index and original provider index
@return pointer to the join if the index belongs to a joined field, otherwise 0 (possibily provider field or added field)*/
const QgsVectorJoinInfo* joinForFieldIndex( int index, int providerFieldCount, int& indexOffset ) const;
@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;

};
Loading

0 comments on commit 81b0930

Please sign in to comment.