[QGIS Commit] r13139 - in trunk/qgis/src/plugins: .
point_displacement_renderer
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Sun Mar 21 18:14:14 EDT 2010
Author: mhugent
Date: 2010-03-21 18:14:14 -0400 (Sun, 21 Mar 2010)
New Revision: 13139
Added:
trunk/qgis/src/plugins/point_displacement_renderer/
trunk/qgis/src/plugins/point_displacement_renderer/CMakeLists.txt
trunk/qgis/src/plugins/point_displacement_renderer/qgsdisplacementplugin.cpp
trunk/qgis/src/plugins/point_displacement_renderer/qgsdisplacementplugin.h
trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrenderer.cpp
trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrenderer.h
trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidget.cpp
trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidget.h
trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidgetbase.ui
Modified:
trunk/qgis/src/plugins/CMakeLists.txt
Log:
[FEATURE]: Add point displacement renderer plugin
Modified: trunk/qgis/src/plugins/CMakeLists.txt
===================================================================
--- trunk/qgis/src/plugins/CMakeLists.txt 2010-03-21 22:06:37 UTC (rev 13138)
+++ trunk/qgis/src/plugins/CMakeLists.txt 2010-03-21 22:14:14 UTC (rev 13139)
@@ -12,6 +12,7 @@
diagram_overlay
evis
labeling
+ point_displacement_renderer
)
IF (POSTGRES_FOUND)
Added: trunk/qgis/src/plugins/point_displacement_renderer/CMakeLists.txt
===================================================================
--- trunk/qgis/src/plugins/point_displacement_renderer/CMakeLists.txt (rev 0)
+++ trunk/qgis/src/plugins/point_displacement_renderer/CMakeLists.txt 2010-03-21 22:14:14 UTC (rev 13139)
@@ -0,0 +1,55 @@
+########################################################
+# Files
+
+SET (POINT_DISPLACEMENT_SRCS
+ qgsdisplacementplugin.cpp
+ qgspointdisplacementrenderer.cpp
+ qgspointdisplacementrendererwidget.cpp
+)
+
+SET (POINT_DISPLACEMENT_UIS
+ qgspointdisplacementrendererwidgetbase.ui
+ )
+
+SET (POINT_DISPLACEMENT_MOC_HDRS
+ qgspointdisplacementrendererwidget.h
+)
+
+########################################################
+# Build
+
+QT4_WRAP_UI (POINT_DISPLACEMENT_UIS_H ${POINT_DISPLACEMENT_UIS})
+
+QT4_WRAP_CPP (POINT_DISPLACEMENT_MOC_SRCS ${POINT_DISPLACEMENT_MOC_HDRS})
+
+ADD_LIBRARY (displacementplugin MODULE
+ ${POINT_DISPLACEMENT_SRCS}
+${POINT_DISPLACEMENT_UIS_H}
+${POINT_DISPLACEMENT_MOC_SRCS}
+)
+
+INCLUDE_DIRECTORIES(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}/../../ui
+ ../../core
+ ../../core/symbology-ng
+ ../../core/spatialindex
+ ../../gui
+ ../../gui/symbology-ng
+ ..
+ .
+)
+
+TARGET_LINK_LIBRARIES(displacementplugin
+ qgis_core
+ qgis_gui
+)
+
+
+########################################################
+# Install
+
+INSTALL(TARGETS displacementplugin
+ RUNTIME DESTINATION ${QGIS_PLUGIN_DIR}
+ LIBRARY DESTINATION ${QGIS_PLUGIN_DIR}
+ )
Added: trunk/qgis/src/plugins/point_displacement_renderer/qgsdisplacementplugin.cpp
===================================================================
--- trunk/qgis/src/plugins/point_displacement_renderer/qgsdisplacementplugin.cpp (rev 0)
+++ trunk/qgis/src/plugins/point_displacement_renderer/qgsdisplacementplugin.cpp 2010-03-21 22:14:14 UTC (rev 13139)
@@ -0,0 +1,86 @@
+/***************************************************************************
+ qgsdisplacementplugin.cpp
+ -------------------------
+ begin : January 26, 2010
+ copyright : (C) 2010 by Marco Hugentobler
+ email : marco at hugis dot net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "qgsdisplacementplugin.h"
+#include "qgisinterface.h"
+#include "qgspointdisplacementrenderer.h"
+#include "qgspointdisplacementrendererwidget.h"
+#include "qgsrendererv2registry.h"
+#include "qgssymbollayerv2registry.h"
+#include <QObject>
+
+static const QString name_ = QObject::tr( "Displacement plugin" );
+static const QString description_ = QObject::tr( "Adds a new renderer that automatically handles point displacement in case they have the same position" );
+static const QString version_ = QObject::tr( "Version 0.1" );
+
+QgsDisplacementPlugin::QgsDisplacementPlugin( QgisInterface* iface ): mIface( iface )
+{
+
+}
+
+QgsDisplacementPlugin::~QgsDisplacementPlugin()
+{
+
+}
+
+void QgsDisplacementPlugin::initGui()
+{
+ //Add new renderer to the registry
+
+ QgsRendererV2Registry::instance()->addRenderer( new QgsRendererV2Metadata( "pointDisplacement",
+ QObject::tr( "point Displacement" ),
+ QgsPointDisplacementRenderer::create, QIcon(),
+ QgsPointDisplacementRendererWidget::create ) );
+}
+
+void QgsDisplacementPlugin::unload()
+{
+ //Remove renderer type from the registry
+ QgsRendererV2Registry::instance()->removeRenderer( "pointDisplacement" );
+}
+
+QGISEXTERN QgisPlugin * classFactory( QgisInterface * theQgisInterfacePointer )
+{
+ return new QgsDisplacementPlugin( theQgisInterfacePointer );
+}
+
+QGISEXTERN QString name()
+{
+ return name_;
+}
+
+QGISEXTERN QString description()
+{
+ return description_;
+}
+
+QGISEXTERN QString version()
+{
+ return version_;
+}
+
+QGISEXTERN int type()
+{
+ return QgisPlugin::UI;
+}
+
+QGISEXTERN void unload( QgisPlugin* thePluginPointer )
+{
+ delete thePluginPointer;
+}
+
+
Added: trunk/qgis/src/plugins/point_displacement_renderer/qgsdisplacementplugin.h
===================================================================
--- trunk/qgis/src/plugins/point_displacement_renderer/qgsdisplacementplugin.h (rev 0)
+++ trunk/qgis/src/plugins/point_displacement_renderer/qgsdisplacementplugin.h 2010-03-21 22:14:14 UTC (rev 13139)
@@ -0,0 +1,40 @@
+/***************************************************************************
+ qgsdisplacementplugin.h
+ -----------------------
+ begin : January 26, 2010
+ copyright : (C) 2010 by Marco Hugentobler
+ email : marco at hugis dot net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSDISPLACEMENTPLUGIN_H
+#define QGSDISPLACEMENTPLUGIN_H
+
+#include "qgisplugin.h"
+
+class QgisInterface;
+
+/**A plugin that adds a point displacement renderer to the symbol registry*/
+class QgsDisplacementPlugin: public QgisPlugin
+{
+ public:
+ QgsDisplacementPlugin( QgisInterface* iface );
+ ~QgsDisplacementPlugin();
+ /**Adds renderer to the registry*/
+ void initGui();
+ /**Removes renderer from the registry*/
+ void unload();
+
+ private:
+ QgisInterface* mIface;
+};
+
+#endif // QGSDISPLACEMENTPLUGIN_H
Added: trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrenderer.cpp
===================================================================
--- trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrenderer.cpp (rev 0)
+++ trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrenderer.cpp 2010-03-21 22:14:14 UTC (rev 13139)
@@ -0,0 +1,557 @@
+/***************************************************************************
+ qgspointdisplacementrenderer.cpp
+ --------------------------------
+ begin : January 26, 2010
+ copyright : (C) 2010 by Marco Hugentobler
+ email : marco at hugis dot net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "qgspointdisplacementrenderer.h"
+#include "qgsgeometry.h"
+#include "qgslogger.h"
+#include "qgsrendererv2registry.h"
+#include "qgsspatialindex.h"
+#include "qgssymbolv2.h"
+#include "qgssymbollayerv2utils.h"
+#include "qgsvectorlayer.h"
+#include <QDomElement>
+#include <QPainter>
+
+#ifndef Q_OS_MACX
+#include <cmath>
+#else
+#include <math.h>
+#endif
+
+QgsPointDisplacementRenderer::QgsPointDisplacementRenderer( const QString& labelAttributeName ): QgsFeatureRendererV2( "pointDisplacement" ), \
+ mLabelAttributeName( labelAttributeName ), mLabelIndex( -1 ), mTolerance( 0.00001 ), mCircleWidth( 0.4 ), mCircleColor( QColor( 125, 125, 125 ) ), mCircleRadiusAddition( 0 ), \
+ mMaxLabelScaleDenominator( -1 )
+{
+ mRenderer = QgsFeatureRendererV2::defaultRenderer( QGis::Point );
+ mCenterSymbol = new QgsMarkerSymbolV2(); //the symbol for the center of a displacement group
+ mDrawLabels = true;
+}
+
+QgsPointDisplacementRenderer::~QgsPointDisplacementRenderer()
+{
+ delete mCenterSymbol;
+ delete mRenderer;
+}
+
+QgsFeatureRendererV2* QgsPointDisplacementRenderer::clone()
+{
+ QgsPointDisplacementRenderer* r = new QgsPointDisplacementRenderer( mLabelAttributeName );
+ r->setEmbeddedRenderer( mRenderer->clone() );
+ r->setDisplacementGroups( mDisplacementGroups );
+ r->setCircleWidth( mCircleWidth );
+ r->setCircleColor( mCircleColor );
+ r->setLabelFont( mLabelFont );
+ r->setLabelColor( mLabelColor );
+ r->setCircleRadiusAddition( mCircleRadiusAddition );
+ r->setMaxLabelScaleDenominator( mMaxLabelScaleDenominator );
+ if ( mCenterSymbol )
+ {
+ r->setCenterSymbol( dynamic_cast<QgsMarkerSymbolV2*>( mCenterSymbol->clone() ) );
+ }
+ return r;
+}
+
+void QgsPointDisplacementRenderer::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool drawVertexMarker )
+{
+ //point position in screen coords
+ QgsGeometry* geom = feature.geometry();
+ QGis::WkbType geomType = geom->wkbType();
+ if ( geomType != QGis::WKBPoint && geomType != QGis::WKBPoint25D )
+ {
+ //can only render point type
+ return;
+ }
+ QPointF pt;
+ _getPoint( pt, context, geom->asWkb() );
+
+
+ //get list of labels and symbols
+ QStringList labelAttributeList;
+ QList<QgsMarkerSymbolV2*> symbolList;
+
+ if ( mDisplacementIds.contains( feature.id() ) )
+ {
+ //create the symbol for the whole display group if the id is the first entry in a display group
+ QList<QMap<int, QgsFeature> >::iterator it = mDisplacementGroups.begin();
+ for ( ; it != mDisplacementGroups.end(); ++it )
+ {
+ //create the symbol for the whole display group if the id is the first entry in a display group
+ if ( feature.id() == it->begin().key() )
+ {
+ QMap<int, QgsFeature>::iterator attIt = it->begin();
+ for ( ; attIt != it->end(); ++attIt )
+ {
+ if ( mDrawLabels )
+ {
+ labelAttributeList << getLabel( attIt.value() );
+ }
+ else
+ {
+ labelAttributeList << QString();
+ }
+ symbolList << dynamic_cast<QgsMarkerSymbolV2*>( mRenderer->symbolForFeature( attIt.value() ) );
+ }
+ }
+ }
+ }
+ else //only one feature
+ {
+ symbolList << dynamic_cast<QgsMarkerSymbolV2*>( mRenderer->symbolForFeature( feature ) );
+ if ( mDrawLabels )
+ {
+ labelAttributeList << getLabel( feature );
+ }
+ else
+ {
+ labelAttributeList << QString();
+ }
+ }
+
+ if ( symbolList.isEmpty() && labelAttributeList.isEmpty() )
+ {
+ return; //display all point symbols for one posi
+ }
+
+
+ //draw symbol
+ double diagonal = 0;
+ double currentWidthFactor; //scale symbol size to map unit and output resolution
+
+ QList<QgsMarkerSymbolV2*>::const_iterator it = symbolList.constBegin();
+ for ( ; it != symbolList.constEnd(); ++it )
+ {
+ if ( *it )
+ {
+ currentWidthFactor = QgsSymbolLayerV2Utils::lineWidthScaleFactor( context, ( *it )->outputUnit() );
+ double currentDiagonal = sqrt( 2 * (( *it )->size() * ( *it )->size() ) ) * currentWidthFactor;
+ if ( currentDiagonal > diagonal )
+ {
+ diagonal = currentDiagonal;
+ }
+ }
+ }
+
+
+ QgsSymbolV2RenderContext symbolContext( context, QgsSymbolV2::MM );
+ double circleAdditionPainterUnits = symbolContext.outputLineWidth( mCircleRadiusAddition );
+ double radius = std::max(( diagonal / 2 ), labelAttributeList.size() * diagonal / 2 / M_PI ) + circleAdditionPainterUnits;
+
+ //draw Circle
+ drawCircle( radius, symbolContext, pt, symbolList.size() );
+
+ QList<QPointF> symbolPositions;
+ QList<QPointF> labelPositions;
+ calculateSymbolAndLabelPositions( pt, labelAttributeList.size(), radius, diagonal, symbolPositions, labelPositions );
+
+ //draw mid point
+ if ( labelAttributeList.size() > 1 )
+ {
+ if ( mCenterSymbol )
+ {
+ mCenterSymbol->renderPoint( pt, context );
+ }
+ else
+ {
+ context.painter()->drawRect( QRectF( pt.x() - symbolContext.outputLineWidth( 1 ), pt.y() - symbolContext.outputLineWidth( 1 ), symbolContext.outputLineWidth( 2 ), symbolContext.outputLineWidth( 2 ) ) );
+ }
+ }
+
+ //draw symbols on the circle
+ drawSymbols( context, symbolList, symbolPositions );
+ //and also the labels
+ drawLabels( pt, symbolContext, labelPositions, labelAttributeList );
+}
+
+void QgsPointDisplacementRenderer::setEmbeddedRenderer( QgsFeatureRendererV2* r )
+{
+ delete mRenderer;
+ mRenderer = r;
+}
+
+QgsSymbolV2* QgsPointDisplacementRenderer::symbolForFeature( QgsFeature& feature )
+{
+ return 0; //not used any more
+}
+
+void QgsPointDisplacementRenderer::startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer )
+{
+ mRenderer->startRender( context, vlayer );
+
+ //create groups with features that have the same position
+ createDisplacementGroups( const_cast<QgsVectorLayer*>( vlayer ), context.extent() );
+ printInfoDisplacementGroups(); //just for debugging
+
+ if ( mLabelAttributeName.isEmpty() )
+ {
+ mLabelIndex = -1;
+ }
+ else
+ {
+ mLabelIndex = vlayer->fieldNameIndex( mLabelAttributeName );
+ }
+
+ if ( mMaxLabelScaleDenominator > 0 && context.rendererScale() > mMaxLabelScaleDenominator )
+ {
+ mDrawLabels = false;
+ }
+ else
+ {
+ mDrawLabels = true;
+ }
+
+ if ( mCenterSymbol )
+ {
+ mCenterSymbol->startRender( context );
+ }
+}
+
+void QgsPointDisplacementRenderer::stopRender( QgsRenderContext& context )
+{
+ QgsDebugMsg( "QgsPointDisplacementRenderer::stopRender" );
+ mRenderer->stopRender( context );
+ if ( mCenterSymbol )
+ {
+ mCenterSymbol->stopRender( context );
+ }
+}
+
+QList<QString> QgsPointDisplacementRenderer::usedAttributes()
+{
+ QList<QString> attributeList;
+ if ( !mLabelAttributeName.isEmpty() )
+ {
+ attributeList.push_back( mLabelAttributeName );
+ }
+ if ( mRenderer )
+ {
+ attributeList.append( mRenderer->usedAttributes() );
+ }
+ return attributeList;
+}
+
+QgsSymbolV2List QgsPointDisplacementRenderer::symbols()
+{
+ if ( mRenderer )
+ {
+ return mRenderer->symbols();
+ }
+ else
+ {
+ return QgsSymbolV2List();
+ }
+}
+
+QgsFeatureRendererV2* QgsPointDisplacementRenderer::create( QDomElement& symbologyElem )
+{
+ QgsPointDisplacementRenderer* r = new QgsPointDisplacementRenderer();
+ r->setLabelAttributeName( symbologyElem.attribute( "labelAttributeName" ) );
+ QFont labelFont;
+ labelFont.fromString( symbologyElem.attribute( "labelFont", "" ) );
+ r->setLabelFont( labelFont );
+ r->setCircleWidth( symbologyElem.attribute( "circleWidth", "0.4" ).toDouble() );
+ r->setCircleColor( QgsSymbolLayerV2Utils::decodeColor( symbologyElem.attribute( "circleColor", "" ) ) );
+ r->setLabelColor( QgsSymbolLayerV2Utils::decodeColor( symbologyElem.attribute( "labelColor", "" ) ) );
+ r->setCircleRadiusAddition( symbologyElem.attribute( "circleRadiusAddition", "0.0" ).toDouble() );
+ r->setMaxLabelScaleDenominator( symbologyElem.attribute( "maxLabelScaleDenominator", "-1" ).toDouble() );
+
+ //look for an embedded renderer <renderer-v2>
+ QDomElement embeddedRendererElem = symbologyElem.firstChildElement( "renderer-v2" );
+ if ( !embeddedRendererElem.isNull() )
+ {
+ QString rendererName = embeddedRendererElem.attribute( "type" );
+ QgsRendererV2AbstractMetadata* metaData = QgsRendererV2Registry::instance()->rendererMetadata( rendererName );
+ if ( metaData )
+ {
+ r->setEmbeddedRenderer( metaData->createRenderer( embeddedRendererElem ) );
+ }
+ }
+
+ //center symbol
+ QDomElement centerSymbolElem = symbologyElem.firstChildElement( "symbol" );
+ if ( !centerSymbolElem.isNull() )
+ {
+ r->setCenterSymbol( dynamic_cast<QgsMarkerSymbolV2*>( QgsSymbolLayerV2Utils::loadSymbol( centerSymbolElem ) ) );
+ }
+ return r;
+}
+
+QDomElement QgsPointDisplacementRenderer::save( QDomDocument& doc )
+{
+ QDomElement rendererElement = doc.createElement( RENDERER_TAG_NAME );
+ rendererElement.setAttribute( "type", "pointDisplacement" );
+ rendererElement.setAttribute( "labelAttributeName", mLabelAttributeName );
+ rendererElement.setAttribute( "labelFont", mLabelFont.toString() );
+ rendererElement.setAttribute( "circleWidth", mCircleWidth );
+ rendererElement.setAttribute( "circleColor", QgsSymbolLayerV2Utils::encodeColor( mCircleColor ) );
+ rendererElement.setAttribute( "labelColor", QgsSymbolLayerV2Utils::encodeColor( mLabelColor ) );
+ rendererElement.setAttribute( "circleRadiusAddition", mCircleRadiusAddition );
+ rendererElement.setAttribute( "maxLabelScaleDenominator", mMaxLabelScaleDenominator );
+
+ if ( mRenderer )
+ {
+ QDomElement embeddedRendererElem = mRenderer->save( doc );
+ rendererElement.appendChild( embeddedRendererElem );
+ }
+ if ( mCenterSymbol )
+ {
+ QDomElement centerSymbolElem = QgsSymbolLayerV2Utils::saveSymbol( "centerSymbol", mCenterSymbol, doc );
+ rendererElement.appendChild( centerSymbolElem );
+ }
+ return rendererElement;
+}
+
+QgsLegendSymbologyList QgsPointDisplacementRenderer::legendSymbologyItems( QSize iconSize )
+{
+ if ( mRenderer )
+ {
+ return mRenderer->legendSymbologyItems( iconSize );
+ }
+ return QgsLegendSymbologyList();
+}
+
+void QgsPointDisplacementRenderer::createDisplacementGroups( QgsVectorLayer* vlayer, const QgsRectangle& viewExtent )
+{
+ if ( !vlayer || ( vlayer->wkbType() != QGis::WKBPoint && vlayer->wkbType() != QGis::WKBPoint25D ) )
+ {
+ return;
+ }
+
+ mDisplacementGroups.clear();
+ mDisplacementIds.clear();
+
+ //use a spatial index to check if there is already a point at a position
+ QgsSpatialIndex spatialIndex;
+
+ //attributes
+ QgsAttributeList attList;
+ QList<QString> attributeStrings = usedAttributes();
+ QList<QString>::const_iterator attStringIt = attributeStrings.constBegin();
+ for ( ; attStringIt != attributeStrings.constEnd(); ++attStringIt )
+ {
+ attList.push_back( vlayer->fieldNameIndex( *attStringIt ) );
+ }
+
+ QgsFeature f;
+ QList<int> intersectList;
+
+ vlayer->select( attList, viewExtent, true, false );
+ while ( vlayer->nextFeature( f ) )
+ {
+ intersectList.clear();
+
+ //check, if there is already a point at that position
+ if ( f.geometry() )
+ {
+ intersectList = spatialIndex.intersects( searchRect( f.geometry()->asPoint() ) );
+ if ( intersectList.empty() )
+ {
+ spatialIndex.insertFeature( f );
+ }
+ else
+ {
+ //go through all the displacement group maps and search an entry where the id equals the result of the spatial search
+ int existingEntry = intersectList.at( 0 );
+ bool found = false;
+ QList<QMap<int, QgsFeature> >::iterator it = mDisplacementGroups.begin();
+ for ( ; it != mDisplacementGroups.end(); ++it )
+ {
+ if ( it->size() > 0 && it->contains( existingEntry ) )
+ {
+ found = true;
+ QgsFeature feature;
+ it->insert( f.id(), f );
+ mDisplacementIds.insert( f.id() );
+ break;
+ }
+ }
+
+ if ( !found )//insert the already existing feature and the new one into a map
+ {
+ QMap<int, QgsFeature> newMap;
+ QgsFeature existingFeature;
+ vlayer->featureAtId( existingEntry, existingFeature );
+ newMap.insert( existingEntry, existingFeature );
+ mDisplacementIds.insert( existingEntry );
+ newMap.insert( f.id(), f );
+ mDisplacementIds.insert( f.id() );
+ mDisplacementGroups.push_back( newMap );
+ }
+ }
+ }
+ }
+ //refresh the selection because the vector layer is going to step through all features now
+ vlayer->select( attList, viewExtent, true, false );
+}
+
+QgsRectangle QgsPointDisplacementRenderer::searchRect( const QgsPoint& p ) const
+{
+ return QgsRectangle( p.x() - mTolerance, p.y() - mTolerance, p.x() + mTolerance, p.y() + mTolerance );
+}
+
+void QgsPointDisplacementRenderer::printInfoDisplacementGroups()
+{
+ int nGroups = mDisplacementGroups.size();
+ QgsDebugMsg( "number of displacement groups:" + QString::number( nGroups ) );
+ for ( int i = 0; i < nGroups; ++i )
+ {
+ QgsDebugMsg( "***************displacement group " + QString::number( i ) );
+ QMap<int, QgsFeature>::const_iterator it = mDisplacementGroups.at( i ).constBegin();
+ for ( ; it != mDisplacementGroups.at( i ).constEnd(); ++it )
+ {
+ QgsDebugMsg( QString::number( it.key() ) );
+ }
+ }
+ QgsDebugMsg( "********all displacement ids*********" );
+ QSet<int>::const_iterator iIt = mDisplacementIds.constBegin();
+ for ( ; iIt != mDisplacementIds.constEnd(); ++iIt )
+ {
+ QgsDebugMsg( QString::number( *iIt ) );
+ }
+}
+
+void QgsPointDisplacementRenderer::setDisplacementGroups( const QList<QMap<int, QgsFeature> >& list )
+{
+ mDisplacementGroups = list;
+ mDisplacementIds.clear();
+
+ QList<QMap<int, QgsFeature> >::const_iterator list_it = mDisplacementGroups.constBegin();
+ for ( ; list_it != mDisplacementGroups.constEnd(); ++list_it )
+ {
+ QMap<int, QgsFeature>::const_iterator map_it = list_it->constBegin();
+ for ( ; map_it != list_it->constEnd(); ++map_it )
+ {
+ mDisplacementIds.insert( map_it.key() );
+ }
+ }
+}
+
+QString QgsPointDisplacementRenderer::getLabel( const QgsFeature& f )
+{
+ QString attribute;
+ QgsAttributeMap attMap = f.attributeMap();
+ if ( attMap.size() > 0 )
+ {
+ QgsAttributeMap::const_iterator valIt = attMap.find( mLabelIndex );
+ if ( valIt != attMap.constEnd() )
+ {
+ attribute = valIt->toString();
+ }
+ }
+ return attribute;
+}
+
+void QgsPointDisplacementRenderer::setCenterSymbol( QgsMarkerSymbolV2* symbol )
+{
+ delete mCenterSymbol;
+ mCenterSymbol = symbol;
+}
+
+
+
+void QgsPointDisplacementRenderer::calculateSymbolAndLabelPositions( const QPointF& centerPoint, int nPosition, double radius, \
+ double symbolDiagonal, QList<QPointF>& symbolPositions, QList<QPointF>& labelShifts ) const
+{
+ symbolPositions.clear();
+ labelShifts.clear();
+
+ double fullPerimeter = 2 * M_PI;
+ double angleStep = fullPerimeter / nPosition;
+ double currentAngle;
+
+ for ( currentAngle = 0.0; currentAngle < fullPerimeter; currentAngle += angleStep )
+ {
+ double sinusCurrentAngle = sin( currentAngle );
+ double cosinusCurrentAngle = cos( currentAngle );
+ QPointF positionShift( radius * sinusCurrentAngle, radius * cosinusCurrentAngle );
+ QPointF labelShift(( radius + symbolDiagonal / 2 ) * sinusCurrentAngle, ( radius + symbolDiagonal / 2 ) * cosinusCurrentAngle );
+ symbolPositions.append( centerPoint + positionShift );
+ labelShifts.append( labelShift );
+ }
+}
+
+void QgsPointDisplacementRenderer::drawCircle( double radiusPainterUnits, QgsSymbolV2RenderContext& context, const QPointF& centerPoint, int nSymbols )
+{
+ QPainter* p = context.renderContext().painter();
+ if ( nSymbols < 2 || !p ) //draw circle only if multiple features
+ {
+ return;
+ }
+
+ //draw Circle
+ QPen circlePen( mCircleColor );
+ circlePen.setWidthF( context.outputLineWidth( mCircleWidth ) );
+ p->setPen( circlePen );
+ p->drawArc( QRectF( centerPoint.x() - radiusPainterUnits, centerPoint.y() - radiusPainterUnits, 2 * radiusPainterUnits, 2 * radiusPainterUnits ), 0, 5760 );
+}
+
+void QgsPointDisplacementRenderer::drawSymbols( QgsRenderContext& context, const QList<QgsMarkerSymbolV2*>& symbolList, const QList<QPointF>& symbolPositions )
+{
+ QList<QPointF>::const_iterator symbolPosIt = symbolPositions.constBegin();
+ QList<QgsMarkerSymbolV2*>::const_iterator symbolIt = symbolList.constBegin();
+ for ( ; symbolPosIt != symbolPositions.constEnd() && symbolIt != symbolList.constEnd(); ++symbolPosIt, ++symbolIt )
+ {
+ if ( *symbolIt )
+ {
+ ( *symbolIt )->renderPoint( *symbolPosIt, context );
+ }
+ }
+}
+
+void QgsPointDisplacementRenderer::drawLabels( const QPointF& centerPoint, QgsSymbolV2RenderContext& context, const QList<QPointF>& labelShifts, const QStringList& labelList )
+{
+ QPainter* p = context.renderContext().painter();
+ if ( !p )
+ {
+ return;
+ }
+
+ QPen labelPen( mLabelColor );
+ p->setPen( labelPen );
+
+ //scale font (for printing)
+ QFont pixelSizeFont = mLabelFont;
+ pixelSizeFont.setPixelSize( context.outputLineWidth( mLabelFont.pointSizeF() * 0.3527 ) );
+ QFont scaledFont = pixelSizeFont;
+ scaledFont.setPixelSize( pixelSizeFont.pixelSize() * context.renderContext().rasterScaleFactor() );
+ p->setFont( scaledFont );
+
+ QFontMetricsF fontMetrics( pixelSizeFont );
+ QPointF currentLabelShift; //considers the signs to determine the label position
+
+ QList<QPointF>::const_iterator labelPosIt = labelShifts.constBegin();
+ QStringList::const_iterator text_it = labelList.constBegin();
+
+ for ( ; labelPosIt != labelShifts.constEnd() && text_it != labelList.constEnd(); ++labelPosIt, ++text_it )
+ {
+ currentLabelShift = *labelPosIt;
+ if ( currentLabelShift.x() < 0 )
+ {
+ currentLabelShift.setX( currentLabelShift.x() - fontMetrics.width( *text_it ) );
+ }
+ if ( currentLabelShift.y() > 0 )
+ {
+ currentLabelShift.setY( currentLabelShift.y() + fontMetrics.ascent() );
+ }
+
+ QPointF drawingPoint( centerPoint + currentLabelShift );
+ p->save();
+ p->translate( drawingPoint.x(), drawingPoint.y() );
+ p->scale( 1.0 / context.renderContext().rasterScaleFactor(), 1.0 / context.renderContext().rasterScaleFactor() );
+ p->drawText( QPointF( 0, 0 ), *text_it );
+ p->restore();
+ }
+}
Added: trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrenderer.h
===================================================================
--- trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrenderer.h (rev 0)
+++ trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrenderer.h 2010-03-21 22:14:14 UTC (rev 13139)
@@ -0,0 +1,145 @@
+/***************************************************************************
+ qgspointdisplacementrenderer.cpp
+ --------------------------------
+ begin : January 26, 2010
+ copyright : (C) 2010 by Marco Hugentobler
+ email : marco at hugis dot net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSPOINTDISPLACEMENTRENDERER_H
+#define QGSPOINTDISPLACEMENTRENDERER_H
+
+#include "qgsfeature.h"
+#include "qgssymbolv2.h"
+#include "qgspoint.h"
+#include "qgsrendererv2.h"
+#include <QFont>
+#include <QSet>
+
+class QgsVectorLayer;
+
+/**A renderer that automatically displaces points with the same position*/
+class QgsPointDisplacementRenderer: public QgsFeatureRendererV2
+{
+ public:
+ QgsPointDisplacementRenderer( const QString& labelAttributeName = "" );
+ ~QgsPointDisplacementRenderer();
+
+ QgsFeatureRendererV2* clone();
+
+ /**Reimplemented from QgsFeatureRendererV2*/
+ void renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer = -1, bool drawVertexMarker = false );
+
+ QgsSymbolV2* symbolForFeature( QgsFeature& feature );
+
+ void startRender( QgsRenderContext& context, const QgsVectorLayer *vlayer );
+
+ void stopRender( QgsRenderContext& context );
+
+ QList<QString> usedAttributes();
+ QgsSymbolV2List symbols();
+
+ //! create a renderer from XML element
+ static QgsFeatureRendererV2* create( QDomElement& symbologyElem );
+ QDomElement save( QDomDocument& doc );
+
+ QgsLegendSymbologyList legendSymbologyItems( QSize iconSize );
+
+ void setLabelAttributeName( const QString& name ) { mLabelAttributeName = name; }
+ QString labelAttributeName() const { return mLabelAttributeName; }
+
+ /**Sets embedded renderer (takes ownership)*/
+ void setEmbeddedRenderer( QgsFeatureRendererV2* r );
+ QgsFeatureRendererV2* embeddedRenderer() { return mRenderer;}
+
+ void setDisplacementGroups( const QList<QMap<int, QgsFeature> >& list );
+
+ void setLabelFont( const QFont& f ) { mLabelFont = f; }
+ QFont labelFont() const { return mLabelFont;}
+
+ void setCircleWidth( double w ) { mCircleWidth = w; }
+ double circleWidth() const { return mCircleWidth; }
+
+ void setCircleColor( const QColor& c ) { mCircleColor = c; }
+ QColor circleColor() const { return mCircleColor; }
+
+ void setLabelColor( const QColor& c ) { mLabelColor = c;}
+ QColor labelColor() const { return mLabelColor; }
+
+ void setCircleRadiusAddition( double d ) { mCircleRadiusAddition = d; }
+ double circleRadiusAddition() const { return mCircleRadiusAddition; }
+
+ void setMaxLabelScaleDenominator( double d ) { mMaxLabelScaleDenominator = d; }
+ double maxLabelScaleDenominator() const { return mMaxLabelScaleDenominator; }
+
+ /**Returns the symbol for the center of a displacement group (but _not_ ownership of the symbol)*/
+ QgsMarkerSymbolV2* centerSymbol() { return mCenterSymbol;}
+ /**Sets the center symbol (takes ownership)*/
+ void setCenterSymbol( QgsMarkerSymbolV2* symbol );
+
+ private:
+
+ /**Embedded renderer. Like This, it is possible to use a classification together with point displacement*/
+ QgsFeatureRendererV2* mRenderer;
+
+ /**Attribute name for labeling. Empty string means no labelling will be done*/
+ QString mLabelAttributeName;
+ /**Label attribute index (or -1 if none). This index is not stored, it is requested in the startRender() method*/
+ int mLabelIndex;
+
+ /**Center symbol for a displacement group*/
+ QgsMarkerSymbolV2* mCenterSymbol;
+
+ /**Tolerance. Points that are closer together are considered as equal*/
+ double mTolerance;
+
+ /**Font that is passed to the renderer*/
+ QFont mLabelFont;
+ QColor mLabelColor;
+ /**Line width for the circle*/
+ double mCircleWidth;
+ /**Color to draw the circle*/
+ QColor mCircleColor;
+ /**Addition to the default circle radius*/
+ double mCircleRadiusAddition;
+ /**Is set internally from startRender() depending on scale denominator*/
+ bool mDrawLabels;
+ /**Maximum scale denominator for label display. Negative number means no scale limitation*/
+ double mMaxLabelScaleDenominator;
+
+ /**Groups of features that have the same position*/
+ QList<QMap<int, QgsFeature> > mDisplacementGroups;
+ /**Set that contains all the ids the display groups (for quicker lookup)*/
+ QSet<int> mDisplacementIds;
+
+ /**Create the displacement groups efficiently using a spatial index*/
+ void createDisplacementGroups( QgsVectorLayer *vlayer, const QgsRectangle& viewExtent );
+ /**Creates a search rectangle with mTolerance*/
+ QgsRectangle searchRect( const QgsPoint& p ) const;
+ /**This is a debugging function to check the entries in the displacement groups*/
+ void printInfoDisplacementGroups();
+
+ /**Returns the label for a feature (using mLabelAttributeName as attribute field)*/
+ QString getLabel( const QgsFeature& f );
+
+ //rendering methods
+ void renderPoint( const QPointF& point, QgsSymbolV2RenderContext& context, const QList<QgsMarkerSymbolV2*>& symbols, \
+ const QStringList& labels );
+
+ //helper functions
+ void calculateSymbolAndLabelPositions( const QPointF& centerPoint, int nPosition, double radius, double symbolDiagonal, QList<QPointF>& symbolPositions, QList<QPointF>& labelShifts ) const;
+ void drawCircle( double radiusPainterUnits, QgsSymbolV2RenderContext& context, const QPointF& centerPoint, int nSymbols );
+ void drawSymbols( QgsRenderContext& context, const QList<QgsMarkerSymbolV2*>& symbolList, const QList<QPointF>& symbolPositions );
+ void drawLabels( const QPointF& centerPoint, QgsSymbolV2RenderContext& context, const QList<QPointF>& labelShifts, const QStringList& labelList );
+};
+
+#endif // QGSPOINTDISPLACEMENTRENDERER_H
Added: trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidget.cpp
===================================================================
--- trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidget.cpp (rev 0)
+++ trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidget.cpp 2010-03-21 22:14:14 UTC (rev 13139)
@@ -0,0 +1,335 @@
+/***************************************************************************
+ qgspointdisplacementrendererwidget.cpp
+ --------------------------------------
+ begin : January 26, 2010
+ copyright : (C) 2010 by Marco Hugentobler
+ email : marco at hugis dot net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "qgspointdisplacementrendererwidget.h"
+#include "qgspointdisplacementrenderer.h"
+#include "qgsrendererv2registry.h"
+#include "qgsfield.h"
+#include "qgsstylev2.h"
+#include "qgssymbolv2selectordialog.h"
+#include "qgssymbollayerv2utils.h"
+#include "qgsvectorlayer.h"
+#include <QColorDialog>
+#include <QFontDialog>
+
+QgsRendererV2Widget* QgsPointDisplacementRendererWidget::create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
+{
+ return new QgsPointDisplacementRendererWidget( layer, style, renderer );
+}
+
+QgsPointDisplacementRendererWidget::QgsPointDisplacementRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ): \
+ QgsRendererV2Widget( layer, style ), mEmbeddedRendererWidget( 0 )
+{
+ if ( !layer )
+ {
+ return;
+ }
+
+ //the renderer only applies to point vector layers
+ if ( layer->wkbType() != QGis::WKBPoint && layer->wkbType() != QGis::WKBPoint25D )
+ {
+ //setup blank dialog
+ mRenderer = 0;
+ setupBlankUi( layer->name() );
+ return;
+ }
+ setupUi( this );
+
+ if ( renderer && renderer->type() == "pointDisplacement" )
+ {
+ mRenderer = dynamic_cast<QgsPointDisplacementRenderer*>( renderer->clone() );
+ }
+ else
+ {
+ mRenderer = new QgsPointDisplacementRenderer();
+ }
+
+ blockAllSignals( true );
+
+ //insert attributes into combo box
+ if ( layer )
+ {
+ const QgsFieldMap layerAttributes = layer->pendingFields();
+ QgsFieldMap::const_iterator it = layerAttributes.constBegin();
+ for ( ; it != layerAttributes.constEnd(); ++it )
+ {
+ mLabelFieldComboBox->addItem( it.value().name() );
+ }
+ mLabelFieldComboBox->addItem( tr( "None" ) );
+
+ QString currentLabelAttribute = mRenderer->labelAttributeName();
+ if ( !currentLabelAttribute.isEmpty() )
+ {
+ mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( currentLabelAttribute ) );
+ }
+ else
+ {
+ mLabelFieldComboBox->setCurrentIndex( mLabelFieldComboBox->findText( tr( "None" ) ) );
+ }
+ }
+
+ //insert possible renderer types
+ QStringList rendererList = QgsRendererV2Registry::instance()->renderersList();
+ QStringList::const_iterator it = rendererList.constBegin();
+ for ( ; it != rendererList.constEnd(); ++it )
+ {
+ if ( *it != "pointDisplacement" )
+ {
+ QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( *it );
+ mRendererComboBox->addItem( m->icon(), m->visibleName(), *it );
+ }
+ }
+
+ mCircleWidthSpinBox->setValue( mRenderer->circleWidth() );
+ mCircleColorButton->setColor( mRenderer->circleColor() );
+ mLabelColorButton->setColor( mRenderer->labelColor() );
+ mCircleModificationSpinBox->setValue( mRenderer->circleRadiusAddition() );
+
+ //scale dependent labelling
+ mMaxScaleDenominatorEdit->setText( QString::number( mRenderer->maxLabelScaleDenominator() ) );
+ mMaxScaleDenominatorEdit->setValidator( new QDoubleValidator( mMaxScaleDenominatorEdit ) );
+ if ( mRenderer->maxLabelScaleDenominator() > 0 )
+ {
+ mScaleDependentLabelsCheckBox->setCheckState( Qt::Checked );
+ }
+ else
+ {
+ mScaleDependentLabelsCheckBox->setCheckState( Qt::Unchecked );
+ mMaxScaleDenominatorEdit->setEnabled( false );
+ }
+
+
+ blockAllSignals( false );
+
+ //set the appropriate renderer dialog
+ if ( mRenderer && mRenderer->embeddedRenderer() )
+ {
+ QString rendererName = mRenderer->embeddedRenderer()->type();
+ int rendererIndex = mRendererComboBox->findData( rendererName );
+ if ( rendererIndex != -1 )
+ {
+ mRendererComboBox->setCurrentIndex( rendererIndex );
+ on_mRendererComboBox_currentIndexChanged( rendererIndex );
+ }
+ }
+
+ updateCenterIcon();
+}
+
+QgsPointDisplacementRendererWidget::~QgsPointDisplacementRendererWidget()
+{
+ delete mRenderer;
+ delete mEmbeddedRendererWidget;
+}
+
+QgsFeatureRendererV2* QgsPointDisplacementRendererWidget::renderer()
+{
+ if ( mRenderer && mEmbeddedRendererWidget )
+ {
+ QgsFeatureRendererV2* embeddedRenderer = mEmbeddedRendererWidget->renderer();
+ if ( embeddedRenderer )
+ {
+ mRenderer->setEmbeddedRenderer( embeddedRenderer->clone() );
+ }
+ }
+ return mRenderer;
+}
+
+void QgsPointDisplacementRendererWidget::on_mLabelFieldComboBox_currentIndexChanged( const QString& text )
+{
+ if ( mRenderer )
+ {
+ if ( text == tr( "None" ) )
+ {
+ mRenderer->setLabelAttributeName( "" );
+ }
+ else
+ {
+ mRenderer->setLabelAttributeName( text );
+ }
+ }
+}
+
+void QgsPointDisplacementRendererWidget::on_mRendererComboBox_currentIndexChanged( int index )
+{
+ QString rendererId = mRendererComboBox->itemData( index ).toString();
+ QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( rendererId );
+ if ( m )
+ {
+ delete mEmbeddedRendererWidget;
+ mEmbeddedRendererWidget = m->createRendererWidget( mLayer, mStyle, mRenderer->embeddedRenderer()->clone() );
+ }
+}
+
+void QgsPointDisplacementRendererWidget::on_mRendererSettingsButton_clicked()
+{
+ if ( mEmbeddedRendererWidget )
+ {
+ //create a dialog with the embedded widget
+ QDialog* d = new QDialog();
+ QGridLayout* layout = new QGridLayout( d );
+ mEmbeddedRendererWidget->setParent( d );
+ QDialogButtonBox* buttonBox = new QDialogButtonBox( d );
+ buttonBox->addButton( QDialogButtonBox::Ok );
+ QObject::connect( buttonBox, SIGNAL( accepted() ), d, SLOT( accept() ) );
+ layout->addWidget( mEmbeddedRendererWidget, 0, 0 );
+ layout->addWidget( buttonBox, 1, 0 );
+ d->exec();
+ mEmbeddedRendererWidget->setParent( 0 );
+ delete d;
+ }
+}
+
+void QgsPointDisplacementRendererWidget::on_mLabelFontButton_clicked()
+{
+ if ( !mRenderer )
+ {
+ return;
+ }
+
+ bool ok;
+ QFont newFont = QFontDialog::getFont( &ok, mRenderer->labelFont(), 0, tr( "Label Font" ) );
+ if ( ok )
+ {
+ mRenderer->setLabelFont( newFont );
+ }
+}
+
+void QgsPointDisplacementRendererWidget::on_mCircleWidthSpinBox_valueChanged( double d )
+{
+ if ( mRenderer )
+ {
+ mRenderer->setCircleWidth( d );
+ }
+}
+
+void QgsPointDisplacementRendererWidget::on_mCircleColorButton_clicked()
+{
+ if ( !mRenderer )
+ {
+ return;
+ }
+
+ QColor newColor = QColorDialog::getColor( mRenderer->circleColor(), 0, tr( "Circle color" ), QColorDialog::ShowAlphaChannel );
+ if ( newColor.isValid() )
+ {
+ mRenderer->setCircleColor( newColor );
+ mCircleColorButton->setColor( newColor );
+ }
+}
+
+void QgsPointDisplacementRendererWidget::on_mLabelColorButton_clicked()
+{
+ if ( !mRenderer )
+ {
+ return;
+ }
+
+ QColor newColor = QColorDialog::getColor( mRenderer->labelColor(), 0, tr( "Label color" ), QColorDialog::ShowAlphaChannel );
+ if ( newColor.isValid() )
+ {
+ mRenderer->setLabelColor( newColor );
+ mLabelColorButton->setColor( newColor );
+ }
+}
+
+void QgsPointDisplacementRendererWidget::on_mCircleModificationSpinBox_valueChanged( double d )
+{
+ if ( !mRenderer )
+ {
+ return;
+ }
+
+ mRenderer->setCircleRadiusAddition( d );
+}
+
+void QgsPointDisplacementRendererWidget::on_mScaleDependentLabelsCheckBox_stateChanged( int state )
+{
+ if ( state == Qt::Unchecked )
+ {
+ mMaxScaleDenominatorEdit->setText( "-1" );
+ mMaxScaleDenominatorEdit->setEnabled( false );
+ }
+ else
+ {
+ mMaxScaleDenominatorEdit->setEnabled( true );
+ }
+}
+
+void QgsPointDisplacementRendererWidget::on_mMaxScaleDenominatorEdit_textChanged( const QString & text )
+{
+ if ( !mRenderer )
+ {
+ return;
+ }
+
+ bool ok;
+ double scaleDenominator = text.toDouble( &ok );
+ if ( ok )
+ {
+ mRenderer->setMaxLabelScaleDenominator( scaleDenominator );
+ }
+}
+
+void QgsPointDisplacementRendererWidget::blockAllSignals( bool block )
+{
+ mLabelFieldComboBox->blockSignals( block );
+ mLabelFontButton->blockSignals( block );
+ mCircleWidthSpinBox->blockSignals( block );
+ mCircleColorButton->blockSignals( block );
+ mRendererComboBox->blockSignals( block );
+ mLabelColorButton->blockSignals( block );
+ mCircleModificationSpinBox->blockSignals( block );
+ mScaleDependentLabelsCheckBox->blockSignals( block );
+ mMaxScaleDenominatorEdit->blockSignals( block );
+ mCenterSymbolPushButton->blockSignals( block );
+}
+
+void QgsPointDisplacementRendererWidget::on_mCenterSymbolPushButton_clicked()
+{
+ if ( !mRenderer || !mRenderer->centerSymbol() )
+ {
+ return;
+ }
+ QgsMarkerSymbolV2* markerSymbol = dynamic_cast<QgsMarkerSymbolV2*>( mRenderer->centerSymbol()->clone() );
+ QgsSymbolV2SelectorDialog dlg( markerSymbol, QgsStyleV2::defaultStyle(), this );
+ if ( dlg.exec() == QDialog::Rejected )
+ {
+ delete markerSymbol;
+ return;
+ }
+ mRenderer->setCenterSymbol( markerSymbol );
+ updateCenterIcon();
+}
+
+void QgsPointDisplacementRendererWidget::updateCenterIcon()
+{
+ QgsMarkerSymbolV2* symbol = mRenderer->centerSymbol();
+ if ( !symbol )
+ {
+ return;
+ }
+ QIcon icon = QgsSymbolLayerV2Utils::symbolPreviewIcon( symbol, mCenterSymbolPushButton->iconSize() );
+ mCenterSymbolPushButton->setIcon( icon );
+}
+
+void QgsPointDisplacementRendererWidget::setupBlankUi( const QString& layerName )
+{
+ QGridLayout* layout = new QGridLayout( this );
+ QLabel* label = new QLabel( tr( "The point displacement renderer only applies to (single) point layers. \n'%1' is not a point layer and cannot be displayed by the point displacement renderer" ).arg( layerName ), this );
+ layout->addWidget( label );
+}
Added: trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidget.h
===================================================================
--- trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidget.h (rev 0)
+++ trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidget.h 2010-03-21 22:14:14 UTC (rev 13139)
@@ -0,0 +1,58 @@
+/***************************************************************************
+ qgspointdisplacementrendererwidget.h
+ ------------------------------------
+ begin : January 26, 2010
+ copyright : (C) 2010 by Marco Hugentobler
+ email : marco at hugis dot net
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef QGSPOINTDISPLACEMENTRENDERERWIDGET_H
+#define QGSPOINTDISPLACEMENTRENDERERWIDGET_H
+
+#include "ui_qgspointdisplacementrendererwidgetbase.h"
+#include "qgsrendererv2widget.h"
+
+class QgsPointDisplacementRenderer;
+
+class QgsPointDisplacementRendererWidget: public QgsRendererV2Widget, private Ui::QgsPointDisplacementRendererWidgetBase
+{
+ Q_OBJECT
+ public:
+ static QgsRendererV2Widget* create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer );
+ QgsPointDisplacementRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer );
+ ~QgsPointDisplacementRendererWidget();
+
+ QgsFeatureRendererV2* renderer();
+
+ private:
+ QgsPointDisplacementRenderer* mRenderer;
+ QgsRendererV2Widget* mEmbeddedRendererWidget;
+
+ void blockAllSignals( bool block );
+ void updateCenterIcon();
+ void setupBlankUi( const QString& layerName );
+
+ private slots:
+ void on_mLabelFieldComboBox_currentIndexChanged( const QString& text );
+ void on_mRendererComboBox_currentIndexChanged( int index );
+ void on_mLabelFontButton_clicked();
+ void on_mCircleWidthSpinBox_valueChanged( double d );
+ void on_mCircleColorButton_clicked();
+ void on_mLabelColorButton_clicked();
+ void on_mCircleModificationSpinBox_valueChanged( double d );
+ void on_mScaleDependentLabelsCheckBox_stateChanged( int state );
+ void on_mMaxScaleDenominatorEdit_textChanged( const QString & text );
+ void on_mCenterSymbolPushButton_clicked();
+ void on_mRendererSettingsButton_clicked();
+};
+
+#endif // QGSPOINTDISPLACEMENTRENDERERWIDGET_H
Added: trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidgetbase.ui
===================================================================
--- trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidgetbase.ui (rev 0)
+++ trunk/qgis/src/plugins/point_displacement_renderer/qgspointdisplacementrendererwidgetbase.ui 2010-03-21 22:14:14 UTC (rev 13139)
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>QgsPointDisplacementRendererWidgetBase</class>
+ <widget class="QWidget" name="QgsPointDisplacementRendererWidgetBase">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>328</width>
+ <height>469</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Form</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_9">
+ <item>
+ <widget class="QLabel" name="mCenterSymbolLabel">
+ <property name="text">
+ <string>Center symbol:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="mCenterSymbolPushButton">
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QLabel" name="mRendererLabel">
+ <property name="text">
+ <string>Renderer:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="mRendererComboBox"/>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <widget class="QPushButton" name="mRendererSettingsButton">
+ <property name="text">
+ <string>Renderer settings...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QGroupBox" name="mDisplacementCirclesGroupBox">
+ <property name="title">
+ <string>Displacement circles</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="0" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLabel" name="mCircleWidthLabel">
+ <property name="text">
+ <string>Circle pen width:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDoubleSpinBox" name="mCircleWidthSpinBox"/>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="mCircleColorLabel">
+ <property name="text">
+ <string>Circle color:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QgsColorButton" name="mCircleColorButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_6">
+ <item>
+ <widget class="QLabel" name="mCircleRadiusLabel">
+ <property name="text">
+ <string>Circle radius modification:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDoubleSpinBox" name="mCircleModificationSpinBox">
+ <property name="minimum">
+ <double>-99.000000000000000</double>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QGroupBox" name="mLabellingGroupBox">
+ <property name="title">
+ <string>Labels</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="mLabelAttributeLabel">
+ <property name="text">
+ <string>Label attribute:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="mLabelFieldComboBox"/>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_8">
+ <item>
+ <widget class="QPushButton" name="mLabelFontButton">
+ <property name="text">
+ <string>Label font...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>94</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_5">
+ <item>
+ <widget class="QLabel" name="mLabelColorLabel">
+ <property name="text">
+ <string>Label color:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QgsColorButton" name="mLabelColorButton">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string/>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="3" column="0">
+ <widget class="QCheckBox" name="mScaleDependentLabelsCheckBox">
+ <property name="text">
+ <string>Use scale dependent labelling</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <layout class="QHBoxLayout" name="horizontalLayout_7">
+ <item>
+ <widget class="QLabel" name="mMaxScaleLabel">
+ <property name="text">
+ <string>max scale denominator:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="mMaxScaleDenominatorEdit"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QgsColorButton</class>
+ <extends>QToolButton</extends>
+ <header>qgscolorbutton.h</header>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>
More information about the QGIS-commit
mailing list