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
This commit is contained in:
wonder 2009-11-18 18:46:12 +00:00
parent ae722e7dca
commit c1676d5137
12 changed files with 148 additions and 93 deletions

View File

@ -1,4 +1,31 @@
/** Labeling engine interface.
* \note Added in QGIS v1.4
*/
class QgsLabelingEngineInterface
{
%TypeHeaderCode
#include <qgsmaprenderer.h>
%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);

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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

View File

@ -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 )
{
}

View File

@ -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

View File

@ -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 )

View File

@ -53,17 +53,6 @@ typedef QList<int> QgsAttributeList;
typedef QSet<int> QgsFeatureIds;
typedef QSet<int> 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;

View File

@ -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<QString, QgsMapLayer*>& layers = QgsMapLayerRegistry::instance()->mapLayers();
for ( QMap<QString, QgsMapLayer*>::iterator it = layers.begin(); it != layers.end(); ++it )
{
QgsMapLayer* layer = it.value();
if ( layer->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( 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<QString, QgsMapLayer*>& layers = QgsMapLayerRegistry::instance()->mapLayers();
for ( QMap<QString, QgsMapLayer*>::iterator it = layers.begin(); it != layers.end(); ++it )
{
QgsMapLayer* layer = it.value();
if ( layer->type() == QgsMapLayer::VectorLayer )
{
QgsVectorLayer* vlayer = dynamic_cast<QgsVectorLayer*>( 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<QgsVectorLayer*>( layer );
// add labeling hook for the newly added layer
vlayer->setLabelingEngine( mLBL );
}

View File

@ -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

View File

@ -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<QgsVectorLayer*, LayerSettings>::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 )

View File

@ -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 );