Skip to content

Commit

Permalink
Do the rendering of map layers within special classes
Browse files Browse the repository at this point in the history
This is an important change: new class (QgsMapLayerRenderer) is introduced
and it keeps all information from layer which is necessary for rendering.
Thanks to that, any changes to map layer will have no impact on rendering that
may be currently underway: if the user changes renderer, rendering will
not crash because it is using a different instance.

Work in progress: only vector layers, no labeling, no diagrams, iterator
still uses some bits from QgsVectorLayer.

Another change: QgsFeatureRendererV2, QgsSymbolV2 do not get access
to QgsVectorLayer - only to fields they need. Point displacement renderer
did more extensive use of QgsVectorLayer - currently it is not functional.
  • Loading branch information
wonder-sk committed Nov 20, 2013
1 parent 036b25e commit 2fcf556
Show file tree
Hide file tree
Showing 44 changed files with 919 additions and 665 deletions.
2 changes: 1 addition & 1 deletion src/app/qgsmaptoolrotatepointsymbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ void QgsMapToolRotatePointSymbols::createPixmapItem( QgsFeature& f )
{
QgsFeatureRendererV2* rv2 = mActiveLayer->rendererV2()->clone();
rv2->setRotationField( "" );
rv2->startRender( renderContext, mActiveLayer );
rv2->startRender( renderContext, mActiveLayer->pendingFields() );

QgsSymbolV2* symbolV2 = rv2->symbolForFeature( f );
if ( symbolV2 )
Expand Down
1 change: 1 addition & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ SET(QGIS_CORE_SRCS

qgsmapsettings.cpp
qgsmaprendererjob.cpp
qgsvectorlayerrenderer.cpp

gps/qgsgpsconnection.cpp
gps/qgsgpsconnectionregistry.cpp
Expand Down
1 change: 0 additions & 1 deletion src/core/composer/qgscomposermap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ void QgsComposerMap::draw( QPainter *painter, const QgsRectangle& extent, const
QgsMapRendererCustomPainterJob job( jobMapSettings, painter );
job.start();
job.waitForFinished();

}

void QgsComposerMap::cache( void )
Expand Down
7 changes: 4 additions & 3 deletions src/core/qgsfeaturerequest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,11 @@ QgsFeatureRequest& QgsFeatureRequest::setSubsetOfAttributes( const QStringList&
mFlags |= SubsetOfAttributes;
mAttrs.clear();

for ( int idx = 0; idx < fields.count(); ++idx )
foreach ( const QString& attrName, attrNames )
{
if ( attrNames.contains( fields[idx].name() ) )
mAttrs.append( idx );
int attrNum = fields.fieldNameIndex( attrName );
if ( attrNum != -1 )
mAttrs.append( attrNum );
}

return *this;
Expand Down
12 changes: 12 additions & 0 deletions src/core/qgsfield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,15 @@ QList<QgsField> QgsFields::toList() const
lst.append( mFields[i].field );
return lst;
}

int QgsFields::fieldNameIndex( const QString& fieldName ) const
{
for ( int idx = 0; idx < count(); ++idx )
{
if ( QString::compare( mFields[idx].field.name(), fieldName, Qt::CaseInsensitive ) == 0 )
{
return idx;
}
}
return -1;
}
5 changes: 5 additions & 0 deletions src/core/qgsfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ class CORE_EXPORT QgsFields
//! Look up field's index from name. Returns -1 on error
int indexFromName( const QString& name ) const { return mNameToIndex.value( name, -1 ); }

//! Look up field's index from name - case insensitive
//! TODO: sort out case sensitive (indexFromName()) vs insensitive (fieldNameIndex()) calls
//! @note added in 2.1
int fieldNameIndex( const QString& fieldName ) const;

//! Utility function to return a list of QgsField instances
QList<QgsField> toList() const;

Expand Down
3 changes: 1 addition & 2 deletions src/core/qgsgeometrycache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

#include "qgsvectorlayereditbuffer.h"

QgsGeometryCache::QgsGeometryCache( QgsVectorLayer* layer )
: L( layer )
QgsGeometryCache::QgsGeometryCache()
{
}

Expand Down
10 changes: 4 additions & 6 deletions src/core/qgsgeometrycache.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
#ifndef QGSGEOMETRYCACHE_H
#define QGSGEOMETRYCACHE_H

#include "qgsgeometry.h"
#include "qgsfeature.h"
#include "qgsrectangle.h"

#include "qgsvectorlayer.h"
#include <QMap>

class CORE_EXPORT QgsGeometryCache
{
public:
QgsGeometryCache( QgsVectorLayer* layer );
QgsGeometryCache();
~QgsGeometryCache();

inline QgsGeometryMap& cachedGeometries() { return mCachedGeometries; }
Expand All @@ -31,10 +33,6 @@ class CORE_EXPORT QgsGeometryCache

protected:

inline QgsVectorLayerEditBuffer* editBuffer() { return L->editBuffer(); }

QgsVectorLayer* L;

/** cache of the committed geometries retrieved *for the current display* */
QgsGeometryMap mCachedGeometries;

Expand Down
6 changes: 6 additions & 0 deletions src/core/qgsmaplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

class QgsRenderContext;
class QgsCoordinateReferenceSystem;
class QgsMapLayerRenderer;

class QDomDocument;
class QKeyEvent;
Expand Down Expand Up @@ -128,6 +129,11 @@ class CORE_EXPORT QgsMapLayer : public QObject
@note added in version 1.6*/
virtual void reload() {}

/** Return new instance of QgsMapLayerRenderer that will be used for rendering of given context
* @note added in 2.1
*/
virtual QgsMapLayerRenderer* createMapRenderer( QgsRenderContext& rendererContext ) { Q_UNUSED( rendererContext ); return 0; }

/** This is the method that does the actual work of
* drawing the layer onto a paint device.
* @param rendererContext describes the extents,
Expand Down
49 changes: 49 additions & 0 deletions src/core/qgsmaplayerrenderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef QGSMAPLAYERRENDERER_H
#define QGSMAPLAYERRENDERER_H

#include <QList>

/**
* Base class for utility classes that encapsulate information necessary
* for rendering of map layers. The rendering is typically done in a background
* thread, so it is necessary to keep all structures required for rendering away
* from the original map layer because it may change any time.
*
* Because the data needs to be copied (to avoid the need for locking),
* is is highly desirable to use copy-on-write where possible. This way,
* the overhead of copying (both memory and CPU) will be kept low.
* Qt containers and various Qt classes use implicit sharing.
*
* The scenario will be:
* 1. renderer job (doing preparation in the GUI thread) calls
* QgsMapLayer::createMapRenderer() and gets instance of this class.
* The instance is initialized at that point and should not need
* additional calls to QgsVectorLayer.
* 2. renderer job (still in GUI thread) stores the renderer for later use.
* 3. renderer job (in worker thread) calls QgsMapLayerRenderer::render()
* 4. renderer job (again in GUI thread) will check errors() and report them
*/
class QgsMapLayerRenderer
{
public:
virtual ~QgsMapLayerRenderer() {}

//! Do the rendering (based on data stored in the class)
virtual bool render() = 0;

//! Container for errors (@todo instead of simple message could have error codes + custom data)
struct Error
{
QString message;
};

typedef QList<Error> ErrorList;

//! Return list of errors (problems) that happened during the rendering
ErrorList errors() const { return mErrors; }

protected:
ErrorList mErrors;
};

#endif // QGSMAPLAYERRENDERER_H
Loading

0 comments on commit 2fcf556

Please sign in to comment.