From c1676d513759d9758bb6528bc098a22b42c82788 Mon Sep 17 00:00:00 2001 From: wonder Date: Wed, 18 Nov 2009 18:46:12 +0000 Subject: [PATCH] Improved labeling engine interface, now connected with QgsMapRenderer instead of individual layers. Also fixes #2108. git-svn-id: http://svn.osgeo.org/qgis/trunk@12174 c8812cc2-4d05-0410-92ff-de0c093fc19c --- python/core/qgsmaprenderer.sip | 36 +++++++++++++++++++++ python/core/qgsrendercontext.sip | 5 +++ src/core/qgsmaprenderer.cpp | 21 ++++++++++++ src/core/qgsmaprenderer.h | 37 +++++++++++++++++++++ src/core/qgsrendercontext.cpp | 10 +++++- src/core/qgsrendercontext.h | 10 ++++++ src/core/qgsvectorlayer.cpp | 25 ++++++--------- src/core/qgsvectorlayer.h | 17 ---------- src/plugins/labeling/labeling.cpp | 48 ++-------------------------- src/plugins/labeling/labeling.h | 5 --- src/plugins/labeling/pallabeling.cpp | 19 +++++++---- src/plugins/labeling/pallabeling.h | 8 +++-- 12 files changed, 148 insertions(+), 93 deletions(-) diff --git a/python/core/qgsmaprenderer.sip b/python/core/qgsmaprenderer.sip index d4fd99180c1..838dca38780 100644 --- a/python/core/qgsmaprenderer.sip +++ b/python/core/qgsmaprenderer.sip @@ -1,4 +1,31 @@ + +/** Labeling engine interface. + * \note Added in QGIS v1.4 + */ +class QgsLabelingEngineInterface +{ +%TypeHeaderCode +#include +%End + +public: + virtual ~QgsLabelingEngineInterface(); + + //! called when we're going to start with rendering + virtual void init() = 0; + //! called when starting rendering of a layer + virtual int prepareLayer(QgsVectorLayer* layer, int& attrIndex) = 0; + //! called for every feature + virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat ) = 0; + //! called when the map is drawn and labels should be placed + virtual void drawLabeling( QgsRenderContext& context ) = 0; + //! called when we're done with rendering + virtual void exit() = 0; + +}; + + /** * \class QgsMapRenderer * \brief Class for rendering map layer set @@ -114,6 +141,15 @@ class QgsMapRenderer : QObject //! Accessor for render context QgsRenderContext* rendererContext(); + //! Labeling engine (NULL if there's no custom engine) + //! \note Added in QGIS v1.4 + QgsLabelingEngineInterface* labelingEngine(); + + //! Set labeling engine. Previous engine (if any) is deleted. + //! Takes ownership of the engine. + //! Added in QGIS v1.4 + void setLabelingEngine(QgsLabelingEngineInterface* iface /Transfer/); + signals: void drawingProgress(int current, int total); diff --git a/python/core/qgsrendercontext.sip b/python/core/qgsrendercontext.sip index 900fb2a7649..3cf83eb1439 100644 --- a/python/core/qgsrendercontext.sip +++ b/python/core/qgsrendercontext.sip @@ -32,6 +32,9 @@ class QgsRenderContext double rendererScale() const; + //! Added in QGIS v1.4 + QgsLabelingEngineInterface* labelingEngine(); + //setters /**Sets coordinate transformation. QgsRenderContext takes ownership and deletes if necessary*/ @@ -44,4 +47,6 @@ class QgsRenderContext void setRasterScaleFactor(double factor); void setRendererScale( double scale ); void setPainter(QPainter* p); + //! Added in QGIS v1.4 + void setLabelingEngine(QgsLabelingEngineInterface* iface); }; diff --git a/src/core/qgsmaprenderer.cpp b/src/core/qgsmaprenderer.cpp index 5878170e12f..4a9745cbc35 100644 --- a/src/core/qgsmaprenderer.cpp +++ b/src/core/qgsmaprenderer.cpp @@ -58,6 +58,8 @@ QgsMapRenderer::QgsMapRenderer() mDestCRS = new QgsCoordinateReferenceSystem( GEO_EPSG_CRS_ID, QgsCoordinateReferenceSystem::EpsgCrsId ); //WGS 84 mOutputUnits = QgsMapRenderer::Millimeters; + + mLabelingEngine = NULL; } QgsMapRenderer::~QgsMapRenderer() @@ -65,6 +67,7 @@ QgsMapRenderer::~QgsMapRenderer() delete mScaleCalculator; delete mDistArea; delete mDestCRS; + delete mLabelingEngine; } @@ -282,6 +285,10 @@ void QgsMapRenderer::render( QPainter* painter ) mySameAsLastFlag = false; } + mRenderContext.setLabelingEngine(mLabelingEngine); + if ( mLabelingEngine ) + mLabelingEngine->init(); + // know we know if this render is just a repeat of the last time, we // can clear caches if it has changed if ( !mySameAsLastFlag ) @@ -572,6 +579,12 @@ void QgsMapRenderer::render( QPainter* painter ) // make sure progress bar arrives at 100%! emit drawingProgress( 1, 1 ); + if ( mLabelingEngine ) + { + mLabelingEngine->drawLabeling( mRenderContext ); + mLabelingEngine->exit(); + } + QgsDebugMsg( "Rendering completed in (seconds): " + QString( "%1" ).arg( renderTime.elapsed() / 1000.0 ) ); mDrawing = false; @@ -1041,3 +1054,11 @@ bool QgsMapRenderer::writeXML( QDomNode & theNode, QDomDocument & theDoc ) return true; } + +void QgsMapRenderer::setLabelingEngine(QgsLabelingEngineInterface* iface) +{ + if (mLabelingEngine) + delete mLabelingEngine; + + mLabelingEngine = iface; +} diff --git a/src/core/qgsmaprenderer.h b/src/core/qgsmaprenderer.h index 33070fc5091..4ec428a6c7b 100644 --- a/src/core/qgsmaprenderer.h +++ b/src/core/qgsmaprenderer.h @@ -34,6 +34,31 @@ class QgsScaleCalculator; class QgsCoordinateReferenceSystem; class QgsDistanceArea; class QgsOverlayObjectPositionManager; +class QgsVectorLayer; +class QgsFeature; + +/** Labeling engine interface. + * \note Added in QGIS v1.4 + */ +class QgsLabelingEngineInterface +{ +public: + virtual ~QgsLabelingEngineInterface() {} + + //! called when we're going to start with rendering + virtual void init() = 0; + //! called when starting rendering of a layer + virtual int prepareLayer(QgsVectorLayer* layer, int& attrIndex) = 0; + //! called for every feature + virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat ) = 0; + //! called when the map is drawn and labels should be placed + virtual void drawLabeling( QgsRenderContext& context ) = 0; + //! called when we're done with rendering + virtual void exit() = 0; + +}; + + /** \ingroup core * A non GUI class for rendering a map layer set onto a QPainter. @@ -146,6 +171,15 @@ class CORE_EXPORT QgsMapRenderer : public QObject //! Accessor for render context QgsRenderContext* rendererContext() {return &mRenderContext;} + //! Labeling engine (NULL if there's no custom engine) + //! \note Added in QGIS v1.4 + QgsLabelingEngineInterface* labelingEngine() { return mLabelingEngine; } + + //! Set labeling engine. Previous engine (if any) is deleted. + //! Takes ownership of the engine. + //! Added in QGIS v1.4 + void setLabelingEngine(QgsLabelingEngineInterface* iface); + signals: void drawingProgress( int current, int total ); @@ -232,6 +266,9 @@ class CORE_EXPORT QgsMapRenderer : public QObject //!Output units OutputUnits mOutputUnits; + + //! Labeling engine (NULL by default) + QgsLabelingEngineInterface* mLabelingEngine; }; #endif diff --git a/src/core/qgsrendercontext.cpp b/src/core/qgsrendercontext.cpp index 189f61e1280..cc81a9ad2b2 100644 --- a/src/core/qgsrendercontext.cpp +++ b/src/core/qgsrendercontext.cpp @@ -18,7 +18,15 @@ #include "qgsrendercontext.h" -QgsRenderContext::QgsRenderContext(): mPainter( 0 ), mCoordTransform( 0 ), mDrawEditingInformation( false ), mForceVectorOutput( true ), mRenderingStopped( false ), mScaleFactor( 1.0 ), mRasterScaleFactor( 1.0 ) +QgsRenderContext::QgsRenderContext() + : mPainter( 0 ), + mCoordTransform( 0 ), + mDrawEditingInformation( false ), + mForceVectorOutput( true ), + mRenderingStopped( false ), + mScaleFactor( 1.0 ), + mRasterScaleFactor( 1.0 ), + mLabelingEngine( NULL ) { } diff --git a/src/core/qgsrendercontext.h b/src/core/qgsrendercontext.h index 0409527ef6e..1a1349df06d 100644 --- a/src/core/qgsrendercontext.h +++ b/src/core/qgsrendercontext.h @@ -24,6 +24,8 @@ class QPainter; +class QgsLabelingEngineInterface; + /** \ingroup core * Contains information about the context of a rendering operation. * The context of a rendering operation defines properties such as @@ -58,6 +60,9 @@ class CORE_EXPORT QgsRenderContext double rendererScale() const {return mRendererScale;} + //! Added in QGIS v1.4 + QgsLabelingEngineInterface* labelingEngine() const { return mLabelingEngine; } + //setters /**Sets coordinate transformation. QgsRenderContext takes ownership and deletes if necessary*/ @@ -70,6 +75,8 @@ class CORE_EXPORT QgsRenderContext void setRasterScaleFactor( double factor ) {mRasterScaleFactor = factor;} void setRendererScale( double scale ) {mRendererScale = scale;} void setPainter( QPainter* p ) {mPainter = p;} + //! Added in QGIS v1.4 + void setLabelingEngine(QgsLabelingEngineInterface* iface) { mLabelingEngine = iface; } private: @@ -100,6 +107,9 @@ class CORE_EXPORT QgsRenderContext /**Map scale*/ double mRendererScale; + + /**Labeling engine (can be NULL)*/ + QgsLabelingEngineInterface* mLabelingEngine; }; #endif diff --git a/src/core/qgsvectorlayer.cpp b/src/core/qgsvectorlayer.cpp index d9d0287aa40..5e488c68755 100644 --- a/src/core/qgsvectorlayer.cpp +++ b/src/core/qgsvectorlayer.cpp @@ -109,8 +109,7 @@ QgsVectorLayer::QgsVectorLayer( QString vectorLayerPath, mVertexMarkerOnlyForSelection( false ), mFetching( false ), mRendererV2( NULL ), - mUsingRendererV2( false ), - mLabelingEngine( NULL ) + mUsingRendererV2( false ) { mActions = new QgsAttributeAction; @@ -686,7 +685,7 @@ void QgsVectorLayer::drawRendererV2( QgsRenderContext& rendererContext, bool lab mRendererV2->renderFeature( fet, rendererContext ); if ( labeling ) - mLabelingEngine->registerFeature( this, fet ); + rendererContext.labelingEngine()->registerFeature( this, fet ); } mRendererV2->stopRender( rendererContext ); @@ -725,7 +724,7 @@ void QgsVectorLayer::drawRendererV2Levels( QgsRenderContext& rendererContext, bo features[sym].append( fet ); if ( labeling ) - mLabelingEngine->registerFeature( this, fet ); + rendererContext.labelingEngine()->registerFeature( this, fet ); } // find out the order @@ -799,10 +798,10 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext ) } bool labeling = FALSE; - if ( mLabelingEngine ) + if ( rendererContext.labelingEngine() ) { int attrIndex; - if ( mLabelingEngine->prepareLayer( this, attrIndex ) ) + if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex ) ) { if ( !attributes.contains( attrIndex ) ) attributes << attrIndex; @@ -859,10 +858,10 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext ) QgsAttributeList attributes = mRenderer->classificationAttributes(); bool labeling = FALSE; - if ( mLabelingEngine ) + if ( rendererContext.labelingEngine() ) { int attrIndex; - if ( mLabelingEngine->prepareLayer( this, attrIndex ) ) + if ( rendererContext.labelingEngine()->prepareLayer( this, attrIndex ) ) { if ( !attributes.contains( attrIndex ) ) attributes << attrIndex; @@ -934,9 +933,9 @@ bool QgsVectorLayer::draw( QgsRenderContext& rendererContext ) //double scale = rendererContext.scaleFactor() / markerScaleFactor; drawFeature( rendererContext, fet, &marker ); - if ( labeling && mLabelingEngine ) + if ( labeling ) { - mLabelingEngine->registerFeature( this, fet ); + rendererContext.labelingEngine()->registerFeature( this, fet ); } ++featureCount; @@ -2256,12 +2255,6 @@ bool QgsVectorLayer::hasLabelsEnabled( void ) const return mLabelOn; } -void QgsVectorLayer::setLabelingEngine( QgsLabelingEngineInterface* engine ) -{ - mLabelingEngine = engine; -} - - bool QgsVectorLayer::startEditing() { if ( !mDataProvider ) diff --git a/src/core/qgsvectorlayer.h b/src/core/qgsvectorlayer.h index 364c8220e02..f59daaf7c68 100644 --- a/src/core/qgsvectorlayer.h +++ b/src/core/qgsvectorlayer.h @@ -53,17 +53,6 @@ typedef QList QgsAttributeList; typedef QSet QgsFeatureIds; typedef QSet QgsAttributeIds; -class QgsLabelingEngineInterface -{ - public: - virtual ~QgsLabelingEngineInterface() {} - virtual int prepareLayer( QgsVectorLayer* layer, int& attrIndex ) = 0; - virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat ) = 0; - //void calculateLabeling() = 0; - //void drawLabeling(QgsRenderContext& context) = 0; -}; - - /** \ingroup core * Vector layer backed by a data source provider. @@ -362,9 +351,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer /** Label is on */ bool hasLabelsEnabled( void ) const; - /** Assign a custom labeling engine with layer. Added in v1.4 */ - void setLabelingEngine( QgsLabelingEngineInterface* engine ); - /** Returns true if the provider is in editing mode */ virtual bool isEditable() const; @@ -747,9 +733,6 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer /** Label */ QgsLabel *mLabel; - QgsLabelingEngineInterface* mLabelingEngine; - - /** Display labels */ bool mLabelOn; diff --git a/src/plugins/labeling/labeling.cpp b/src/plugins/labeling/labeling.cpp index 21dc16005a2..7c7e03fb555 100644 --- a/src/plugins/labeling/labeling.cpp +++ b/src/plugins/labeling/labeling.cpp @@ -126,27 +126,9 @@ void Labeling::initGui() mTool = new LabelingTool( mLBL, mQGisIface->mapCanvas() ); - connect( mQGisIface->mapCanvas(), SIGNAL( renderComplete( QPainter * ) ), this, SLOT( doLabeling( QPainter * ) ) ); + // map renderer takes ownership of the labeling engine + mQGisIface->mapCanvas()->mapRenderer()->setLabelingEngine( mLBL ); - // connect to newly added layers so the labeling hook will be set up - connect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( layerWasAdded( QgsMapLayer* ) ) ); - - // add labeling hooks to all existing layers - QMap& layers = QgsMapLayerRegistry::instance()->mapLayers(); - for ( QMap::iterator it = layers.begin(); it != layers.end(); ++it ) - { - QgsMapLayer* layer = it.value(); - if ( layer->type() == QgsMapLayer::VectorLayer ) - { - QgsVectorLayer* vlayer = dynamic_cast( layer ); - vlayer->setLabelingEngine( mLBL ); - } - } -} - -void Labeling::doLabeling( QPainter * painter ) -{ - mLBL->doLabeling( painter, mQGisIface->mapCanvas()->extent() ); } // Slot called when the menu item is triggered @@ -187,21 +169,6 @@ void Labeling::unload() mQGisIface->mapCanvas()->unsetMapTool( mTool ); delete mTool; - // remove labeling hook from all layers! - QMap& layers = QgsMapLayerRegistry::instance()->mapLayers(); - for ( QMap::iterator it = layers.begin(); it != layers.end(); ++it ) - { - QgsMapLayer* layer = it.value(); - if ( layer->type() == QgsMapLayer::VectorLayer ) - { - QgsVectorLayer* vlayer = dynamic_cast( layer ); - vlayer->setLabelingEngine( NULL ); - } - } - - disconnect( QgsMapLayerRegistry::instance(), SIGNAL( layerWasAdded( QgsMapLayer* ) ), this, SLOT( layerWasAdded( QgsMapLayer* ) ) ); - disconnect( mQGisIface->mapCanvas(), SIGNAL( renderComplete( QPainter * ) ), this, SLOT( doLabeling( QPainter * ) ) ); - // remove the GUI mQGisIface->removePluginMenu( "&Labeling", mQActionPointer ); mQGisIface->removeToolBarIcon( mQActionPointer ); @@ -213,17 +180,8 @@ void Labeling::unload() delete mActionTool; */ - delete mLBL; -} + mQGisIface->mapCanvas()->mapRenderer()->setLabelingEngine( NULL ); -void Labeling::layerWasAdded( QgsMapLayer* layer ) -{ - if ( layer->type() != QgsMapLayer::VectorLayer ) - return; // not interested in rasters - - QgsVectorLayer* vlayer = dynamic_cast( layer ); - // add labeling hook for the newly added layer - vlayer->setLabelingEngine( mLBL ); } diff --git a/src/plugins/labeling/labeling.h b/src/plugins/labeling/labeling.h index 6d86526a367..c03f9fb759f 100644 --- a/src/plugins/labeling/labeling.h +++ b/src/plugins/labeling/labeling.h @@ -58,14 +58,9 @@ class Labeling: public QObject, public QgisPlugin //! unload the plugin void unload(); - //! hook to renderComplete signal - void doLabeling( QPainter* painter ); - //! start labeling map tool void setTool(); - void layerWasAdded( QgsMapLayer* theMapLayer ); - private: //! Pointer to the QGIS interface object diff --git a/src/plugins/labeling/pallabeling.cpp b/src/plugins/labeling/pallabeling.cpp index 3d45cfb8143..7444a87914d 100644 --- a/src/plugins/labeling/pallabeling.cpp +++ b/src/plugins/labeling/pallabeling.cpp @@ -268,14 +268,13 @@ PalLabeling::PalLabeling( QgsMapRenderer* mapRenderer ) mShowingCandidates = FALSE; mShowingAllLabels = FALSE; - - initPal(); } PalLabeling::~PalLabeling() { - delete mPal; + // make sure we've freed everything + exit(); } @@ -357,7 +356,7 @@ void PalLabeling::registerFeature( QgsVectorLayer* layer, QgsFeature& f ) } -void PalLabeling::initPal() +void PalLabeling::init() { // delete if exists already if ( mPal ) @@ -383,6 +382,12 @@ void PalLabeling::initPal() mPal->setPolyP( mCandPolygon ); } +void PalLabeling::exit() +{ + delete mPal; + mPal = NULL; +} + LayerSettings& PalLabeling::layer( const char* layerName ) { QHash::iterator lit; @@ -396,8 +401,10 @@ LayerSettings& PalLabeling::layer( const char* layerName ) } -void PalLabeling::doLabeling( QPainter* painter, QgsRectangle extent ) +void PalLabeling::drawLabeling( QgsRenderContext& context ) { + QPainter* painter = context.painter(); + QgsRectangle extent = context.extent(); QTime t; t.start(); @@ -478,8 +485,6 @@ void PalLabeling::doLabeling( QPainter* painter, QgsRectangle extent ) // labeling is done: clear the active layers hashtable mActiveLayers.clear(); - // re-create PAL - initPal(); } void PalLabeling::numCandidatePositions( int& candPoint, int& candLine, int& candPolygon ) diff --git a/src/plugins/labeling/pallabeling.h b/src/plugins/labeling/pallabeling.h index 560521b1f59..4dbfbf2edb6 100644 --- a/src/plugins/labeling/pallabeling.h +++ b/src/plugins/labeling/pallabeling.h @@ -104,8 +104,6 @@ class PalLabeling : public QgsLabelingEngineInterface LayerSettings& layer( const char* layerName ); - void doLabeling( QPainter* painter, QgsRectangle extent ); - void numCandidatePositions( int& candPoint, int& candLine, int& candPolygon ); void setNumCandidatePositions( int candPoint, int candLine, int candPolygon ); @@ -123,10 +121,16 @@ class PalLabeling : public QgsLabelingEngineInterface // implemented methods from labeling engine interface + //! called when we're going to start with rendering + virtual void init(); //! hook called when drawing layer before issuing select() virtual int prepareLayer( QgsVectorLayer* layer, int& attrIndex ); //! hook called when drawing for every feature in a layer virtual void registerFeature( QgsVectorLayer* layer, QgsFeature& feat ); + //! called when the map is drawn and labels should be placed + virtual void drawLabeling( QgsRenderContext& context ); + //! called when we're done with rendering + virtual void exit(); void drawLabelCandidateRect( pal::LabelPosition* lp, QPainter* painter, const QgsMapToPixel* xform );