[Qgis-developer] New Vector API

Matthias Kuhn matthias.kuhn at gmx.ch
Wed May 22 12:01:54 PDT 2013


Hi List, Hi Martin,

TLDR; New QgsFeatureRequest filters
- FilterExpression
- FilterFids
Available here [1]

For another project I'm currently working on, I need additional filter
possibilities in QgsFeatureRequest to filter with a QgsExpression.
As I
- did not want to repeat the code inside each iterator
- but need the possibility to override the behavior (e.g.
vectorlayerfeatureiterator only needs to filter changed features bot
does not need to refilter features already filtered by the provider)
I extended QgsAbstractFeatureIterator to handle this but allow derived
classes to override the method if they want. I introduced a small API
change such that, the nextFeature method calls
nextFeatureFilterExpression which can be overridden by subclasses. Main
filtering is done within a new method fetchFeature which gets called by
nextFeature and should not perform any filtering as long as
FilterExpression is not implemented.
Same goes for FilterFids which takes multiple featureids but is now
implemented to iterate over all features, but can easily be
reimplemented inside providers to be executed on the server side.
The change updates the API, but only for the implementation of iterators
and not for any module which uses the iterator (same nextFeature call as
before).

Anyway, before spending more time on this, I'd like to hear your opinion.

Matthias

[1] https://github.com/matthias-kuhn/Quantum-GIS/tree/request-filters

On 28.12.2012 17:03, Martin Dobias wrote:
> Hi everyone,
>
> it seems that now it is a good time to ask for a broader review of the
> work I have been doing during recent months: essentially making QGIS
> vector API more flexible and more ready for introduction of threading
> for rendering. That resulted in a greater refactoring of some parts of
> QgsVectorLayer class and QgsVectorDataProvider implementations.
> Everything is in new_vector_api branch in QGIS repository on GitHub
> [1].
>
> There are few things that are not finished, but should not take too
> much work to sort out:
> - disabled providers - mssql, osm, sqlanywhere, wfs - not yet updated
to new API
> - disabled mapserver - there are few things to update
>
> If no serious problems will be found, I would like to merge the branch
> to master and continue working on that on master branch to avoid the
> possibility to drift (again) too much from the quick development that
> happens on master. In short term I plan to do some polishing and
> fixing bugs, then eventually start looking at the threading again.
>
> For more details about what happened in the branch, see the text below
> (long read!). A great help from early testers would be to compile the
> branch, try to do some "usual" stuff with vectors and see if things
> break apart (crashes? data corruption?).
>
> Looking forward to your comments!
>
> Regards
> Martin
>
> [1] https://github.com/qgis/Quantum-GIS/tree/new_vector_api
>
>
>
> QGIS VECTOR API CHANGES
>
> 1. QgsFeature (changes)
>
> a) access to attributes by name. Vector data providers and vector
> layer assign pointer to the fields in QgsFeature, so it is possible to
> set/get attributes by their name. This is not as efficient as with
> direct access by index, but often this convenience is useful for
> users.
>
> b) attributes are stored in a QVector container rather than a QMap.
> The major advantage is simplification of logic related to handling of
> attributes: it's not possible to have "holes" in the array of
> fields/attributes. Currently it is possible that for example layer
> with three fields returns indexes 0,1,3 - but it is not so common nor
> obvious, so it's a common source of errors. After refactoring there
> must not be any holes, so a layer with three fields always returns
> indexes 0,1,2. When iterating over layer's features, QgsFeature always
> contains a vector of all layer's attributes. In case the client has
> not requested attributes to be fetched, the attributes contain invalid
> values.
>
>
> 2. QgsFields (new class)
>
> Just like attributes within a feature are stored in a vector instead
> of map, also layer's fields are now stored in a vector. QgsFields is a
> new class that mimics QVector API and adds two more pieces of
> functionality:
>
> a) fast lookup of field index from name. When QgsFields is populated
> with fields, it creates a map of fields that facilitates fast lookups
>
> b) detection of field origin. When working with a vector layer, it is
> sometimes useful to find out origin of the field - whether it comes
> from provider, from a join or whether it is a newly added field (not
> committed). In the future we could add also expression-based fields,
> creating a field calculator that calculates the values on the fly.
>
>
> 3. QgsFeatureRequest (new class)
>
> Class that encapsulates requests for features to a vector layer or
> vector data provider. Right now in master branch, the request is
> defined by arguments to select() method. That's not very flexible nor
> simple to use. Feature request class allows easier extensibility in
> future (support generic expression filter, native provider's SQL
> filter...).
>
> Without any customization, the request will ask for all features with
> geometries and attributes - somehow better default that the current
> one that does not fetch attributes if their list is not explicitly
> given.
>
> (I'm not yet completely happy with the API of this class, so it may be
> changed to some degree. Suggestions are welcome.)
>
> Examples:
> - fetch all features:
>     QgsFeatureRequest()
> - fetch all features, only one attribute
>     QgsFeatureRequest().setSubsetOfAttributes(QStringList("myfield"),
> provider->fields())
> - fetch all features, without geometries
>     QgsFeatureRequest().setFlags(QgsFeatureRequest::NoGeometry)
> - fetch only features from particular extent
>     QgsFeatureRequest().setFilterRect(QgsRectangle(0,0,1,1))
> - fetch only one feature
>     QgsFeatureRequest().setFilterFid(45)
>
>
>
> 4. QgsFeatureIterator (new class)
>
> The iterator class allows iteration over features of a vector layer or
> a provider. It contains the usual nextFeature() method that fills
> given QgsFeature class with data.
>
> Internally, this class is a wrapper around QgsAbstractFeatureIterator
> interface that is implemented by each vector data provider and by
> vector layer. In theory we could use directly
> QgsAbstractFeatureIterator pointers, but this wrapper allows us to use
> it as a local variable, so it gets destroyed automatically when it
> gets out of scope, not requiring an explicit "delete" call that would
> be necessary with a pointer (easy to forget, right?)
>
>
> 5. Access to features
>
> Vector layer and providers implement one important method call:
> getFeatures(). It takes single argument (QgsFeatureRequest) and
> returns QgsFeatureIterator. This replaces select(), nextFeature(),
> rewind() and featureAtId() methods.
>
> This approach allows users to create multiple iterators over a vector
> layer (or a vector data provider). But currently that's not supported
> because this needs support in the providers. At some point, we could
> add support for simultaneous iterators - something that old API does
> not allow at all.
>
> When QgsFeatureIterator instance of a particular layer is closed (by
> calling close() or destructed), then a new getFeatures() call may be
> issued.
>
>
> 6. QgsVectorLayerEditBuffer (new class)
>
> All editing functionality of vector layer has been moved out of
> QgsVectorLayer into a new class that stores everything related to
> editing: added features, removed features, changed geometries, changed
> attribute values, added attributes, removed attributes. This class is
> accessible from QgsVectorLayer, but it exists only when the layer is
> in editing mode - it is deleted once features are rolled back or
> committed.
>
> The undo/redo support has been completely rewritten and greatly
> simplified: instead of one undo command that gathers changes within
> the edit buffer, there is now one undo command implementation for each
> action. The undo commands can be grouped together with QUndoStack
> macros. The new implementation ensures that the undo stack does not
> get out of sync, because all editing changes are stored onto undo
> stack (unlike current implementation in master branch where
> begin/end-UndoCommand() methods must be called before/after edit
> operations to ensure correct behavior of undo).
>
>
> 7. QgsVectorLayerEditUtils (new class)
>
> Advanced editing operations that operate on vector layers (e.g. add
> part) that can be composed from one or more simple edit operations
> have been moved out of QgsVectorLayer and its edit buffer, so that the
> vector layer API is not polluted by methods that do not need access to
> its private members.
>
>
> 8. QgsVectorLayerCache (new class)
>
> To speed up geometry editing, QGIS keeps a cache of geometries
> currently shown in map canvas. This cache has been decoupled from
> editing operations and moved to a separate class to keep things tidy.
> In the future we should be able to add more general caching scheme to
> allow faster rendering of vectors. Also, this might be a good place to
> store index of feature ID -> row number that is calculated every time
> when attribute table is opened.
>
>
> 9. Python
>
> Python API has been updated to support functionality from the points
> above, that is access by attribute name and support for python
> iterators, e.g.:
>
> for feature in layer.getFeatures(request):
>   print feature["road_id"]
> _______________________________________________
> Qgis-developer mailing list
> Qgis-developer at lists.osgeo.org
> http://lists.osgeo.org/mailman/listinfo/qgis-developer




More information about the Qgis-developer mailing list