diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index fe8fceca5838..a8c9275a5415 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -36,6 +36,7 @@ SET(QGIS_CORE_SRCS symbology-ng/qgscategorizedsymbolrendererv2.cpp symbology-ng/qgsgraduatedsymbolrendererv2.cpp symbology-ng/qgsrulebasedrendererv2.cpp + symbology-ng/qgsmaskrendererv2.cpp symbology-ng/qgsvectorcolorrampv2.cpp symbology-ng/qgscptcityarchive.cpp symbology-ng/qgsstylev2.cpp @@ -583,6 +584,7 @@ SET(QGIS_CORE_HDRS symbology-ng/qgsrendererv2registry.h symbology-ng/qgsrulebasedrendererv2.h symbology-ng/qgssinglesymbolrendererv2.h + symbology-ng/qgsmaskrendererv2.h symbology-ng/qgsstylev2.h symbology-ng/qgssvgcache.h symbology-ng/qgssymbollayerv2.h diff --git a/src/core/symbology-ng/qgsmaskrendererv2.cpp b/src/core/symbology-ng/qgsmaskrendererv2.cpp new file mode 100644 index 000000000000..ddd45cd4a3bd --- /dev/null +++ b/src/core/symbology-ng/qgsmaskrendererv2.cpp @@ -0,0 +1,303 @@ +/*************************************************************************** + qgsmaskrendererv2.cpp + --------------------- + begin : April 2014 + copyright : (C) 2014 Hugo Mercier / Oslandia + email : hugo dot mercier at oslandia dot com + *************************************************************************** + * * + * 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 "qgsmaskrendererv2.h" + +#include "qgssymbolv2.h" +#include "qgssymbollayerv2utils.h" + +#include "qgslogger.h" +#include "qgsfeature.h" +#include "qgsvectorlayer.h" +#include "qgssymbollayerv2.h" +#include "qgsogcutils.h" + +#include +#include + +QgsMaskRendererV2::QgsMaskRendererV2( const QgsFeatureRendererV2* subRenderer ) + : QgsFeatureRendererV2( "maskRenderer" ) +{ + if ( subRenderer ) { + setEmbeddedRenderer( subRenderer ); + } + else { + mSubRenderer.reset( QgsFeatureRendererV2::defaultRenderer( QGis::Polygon ) ); + } +} + +QgsMaskRendererV2::~QgsMaskRendererV2() +{ +} + +void QgsMaskRendererV2::setEmbeddedRenderer( const QgsFeatureRendererV2* subRenderer ) +{ + if ( subRenderer ) { + mSubRenderer.reset( const_cast(subRenderer)->clone() ); + } + else { + mSubRenderer.reset( 0 ); + } +} + +const QgsFeatureRendererV2* QgsMaskRendererV2::embeddedRenderer() const +{ + return mSubRenderer.data(); +} + +void QgsMaskRendererV2::startRender( QgsRenderContext& context, const QgsFields& fields ) +{ + if ( !mSubRenderer ) { + return; + } + + mSubRenderer->startRender( context, fields ); + mFeaturesCategoryMap.clear(); + mFeatureDecorations.clear(); + mFields = fields; +} + +bool QgsMaskRendererV2::renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer, bool selected, bool drawVertexMarker ) +{ + Q_UNUSED( context ); + + // Features are grouped by category of symbols (returned by symbol(s)ForFeature) + // This way, users can have multiple inverted polygon fills for a layer, + // for instance, with rule based renderer and different symbols + // that have transparency. + // + // In order to assign a unique category to a set of symbols + // during each rendering session (between startRender() and stopRender()), + // we build an unique id as a QByteArray that is the concatenation + // of each symbol's memory address. + // The only assumption made here is that symbol(s)ForFeature will + // always return the same address for the same symbol(s) shared amongst + // different features. + // This QByteArray can then be used as a key for a QMap where the list of + // features for this category is stored + QByteArray catId; + if ( capabilities() & MoreSymbolsPerFeature ) { + QgsSymbolV2List syms( mSubRenderer->symbolsForFeature( feature ) ); + foreach ( QgsSymbolV2* sym, syms ) + { + // append the memory address + catId.append( reinterpret_cast(&sym), sizeof(sym) ); + } + } + else + { + QgsSymbolV2* sym = mSubRenderer->symbolForFeature( feature ); + if (sym) { + catId.append( reinterpret_cast(&sym), sizeof(sym) ); + } + } + if ( !catId.isEmpty() ) + { + mFeaturesCategoryMap[catId].append( feature ); + } + + // store this feature as a feature to render with decoration if needed + if ( selected || drawVertexMarker ) + { + mFeatureDecorations.append( FeatureDecoration( feature, selected, drawVertexMarker, layer) ); + } + + return true; +} + +void QgsMaskRendererV2::stopRender( QgsRenderContext& context ) +{ + if ( !mSubRenderer ) { + return; + } + + // We build here a "reversed" geometry of all the polygons + // + // The final geometry is a multipolygon F, with : + // * the first polygon of F having the current extent as its exterior ring + // * each polygon's exterior ring is added as interior ring of the first polygon of F + // * each polygon's interior ring is added as new polygons in F + // + // No validity check is done, on purpose, it will be very slow and painting + // operations do not need geometries to be valid + for ( FeatureCategoryMap::iterator cit = mFeaturesCategoryMap.begin(); cit != mFeaturesCategoryMap.end(); ++cit) + { + QgsMultiPolygon geom; + geom.push_back( QgsPolygon() ); + + // build a rectangle out of the current extent + QgsRectangle e = context.extent(); + // add some space to hide borders + e.scale(2.0); + QgsPolyline extent_ring; + extent_ring.push_back( QgsPoint(e.xMinimum(), e.yMinimum()) ); + extent_ring.push_back( QgsPoint(e.xMaximum(), e.yMinimum()) ); + extent_ring.push_back( QgsPoint(e.xMaximum(), e.yMaximum()) ); + extent_ring.push_back( QgsPoint(e.xMinimum(), e.yMaximum()) ); + extent_ring.push_back( QgsPoint(e.xMinimum(), e.yMinimum()) ); + geom[0].push_back( extent_ring ); + + for ( QList::iterator fit = cit.value().begin(); fit != cit.value().end(); ++fit ) + { + if ( ! fit->geometry() ) { + continue; + } + QgsMultiPolygon multi; + if ( (fit->geometry()->wkbType() == QGis::WKBPolygon) || (fit->geometry()->wkbType() == QGis::WKBPolygon25D) ) { + multi.push_back( fit->geometry()->asPolygon() ); + } + else if ( (fit->geometry()->wkbType() == QGis::WKBMultiPolygon) || (fit->geometry()->wkbType() == QGis::WKBMultiPolygon25D) ) { + multi = fit->geometry()->asMultiPolygon(); + } + for ( int i = 0; i < multi.size(); i++ ) { + // add the exterior ring as interior ring + geom[0].push_back( multi[i][0] ); + // add interior rings as new exterior rings + for ( int j = 1; j < multi[i].size(); j++ ) { + QgsPolygon new_poly; + new_poly.push_back( multi[i][j] ); + geom.push_back( new_poly ); + } + } + } + + QgsFeature feat( cit.value()[0] ); + feat.setGeometry( QgsGeometry::fromMultiPolygon( geom ) ); + mSubRenderer->renderFeature( feat, context ); + } + + // when no features are visible, we still have to draw the exterior rectangle + if ( mFeaturesCategoryMap.isEmpty() ) + { + QgsRectangle e = context.extent(); + // add some space to hide borders + e.scale(2.0); + QgsFeature feat( mFields ); + feat.setGeometry( QgsGeometry::fromRect(e) ); + mSubRenderer->renderFeature( feat, context ); + } + + // draw feature decorations + foreach (FeatureDecoration deco, mFeatureDecorations ) + { + mSubRenderer->renderFeature( deco.feature, context, deco.layer, deco.selected, deco.drawMarkers ); + } + + mSubRenderer->stopRender( context ); +} + +QString QgsMaskRendererV2::dump() const +{ + if ( !mSubRenderer ) { + return "MASK: NULL"; + } + return "MASK [" + mSubRenderer->dump() + "]"; +} + +QgsFeatureRendererV2* QgsMaskRendererV2::clone() +{ + QgsMaskRendererV2* r = new QgsMaskRendererV2( mSubRenderer.data() ); + return r; +} + +QgsFeatureRendererV2* QgsMaskRendererV2::create( QDomElement& element ) +{ + QgsMaskRendererV2* r = new QgsMaskRendererV2(); + //look for an embedded renderer + QDomElement embeddedRendererElem = element.firstChildElement( "renderer-v2" ); + if ( !embeddedRendererElem.isNull() ) + { + r->setEmbeddedRenderer( QgsFeatureRendererV2::load( embeddedRendererElem ) ); + } + return r; +} + +QDomElement QgsMaskRendererV2::save( QDomDocument& doc ) +{ + QDomElement rendererElem = doc.createElement( RENDERER_TAG_NAME ); + rendererElem.setAttribute( "type", "maskRenderer" ); + + if ( mSubRenderer ) + { + QDomElement embeddedRendererElem = mSubRenderer->save( doc ); + rendererElem.appendChild( embeddedRendererElem ); + } + + return rendererElem; +} + +QgsSymbolV2* QgsMaskRendererV2::symbolForFeature( QgsFeature& feature ) +{ + if ( !mSubRenderer ) { + return 0; + } + return mSubRenderer->symbolForFeature( feature ); +} + +QgsSymbolV2List QgsMaskRendererV2::symbolsForFeature( QgsFeature& feature ) +{ + if ( !mSubRenderer ) { + return QgsSymbolV2List(); + } + return mSubRenderer->symbolsForFeature( feature ); +} + +QgsSymbolV2List QgsMaskRendererV2::symbols() +{ + if ( !mSubRenderer ) { + return QgsSymbolV2List(); + } + return mSubRenderer->symbols(); +} + +int QgsMaskRendererV2::capabilities() +{ + if ( !mSubRenderer ) { + return 0; + } + return mSubRenderer->capabilities(); +} + +QList QgsMaskRendererV2::usedAttributes() +{ + if ( !mSubRenderer ) { + return QList(); + } + return mSubRenderer->usedAttributes(); +} + +QgsLegendSymbologyList QgsMaskRendererV2::legendSymbologyItems( QSize iconSize ) +{ + if ( !mSubRenderer ) { + return QgsLegendSymbologyList(); + } + return mSubRenderer->legendSymbologyItems( iconSize ); +} + +QgsLegendSymbolList QgsMaskRendererV2::legendSymbolItems( double scaleDenominator, QString rule ) +{ + if ( !mSubRenderer ) { + return QgsLegendSymbolList(); + } + return mSubRenderer->legendSymbolItems( scaleDenominator, rule ); +} + +bool QgsMaskRendererV2::willRenderFeature( QgsFeature& feat ) +{ + if ( !mSubRenderer ) { + return false; + } + return mSubRenderer->willRenderFeature( feat ); +} diff --git a/src/core/symbology-ng/qgsmaskrendererv2.h b/src/core/symbology-ng/qgsmaskrendererv2.h new file mode 100644 index 000000000000..db9c02fa8f21 --- /dev/null +++ b/src/core/symbology-ng/qgsmaskrendererv2.h @@ -0,0 +1,138 @@ +/*************************************************************************** + qgsmaskrendererv2.h + --------------------- + begin : April 2014 + copyright : (C) 2014 Hugo Mercier / Oslandia + email : hugo dot mercier at oslandia dot com + *************************************************************************** + * * + * 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 QGSMASKRENDERERV2_H +#define QGSMASKRENDERERV2_H + +#include "qgis.h" +#include "qgsrendererv2.h" +#include "qgssymbolv2.h" +#include "qgsexpression.h" +#include "qgsfeature.h" +#include + +/** + * QgsMaskRendererV2 is a polygon-only feature renderer used to + * display features inverted, where the exterior is turned to an interior + * and where the exterior theoretically spans the entire plane, allowing + * to mask the surroundings of some features. + * + * It is designed on top of another feature renderer, which is called "embedded" + * Most of the methods are then only proxies to the embedded renderer. + * + * Features are collected to form one "inverted" polygon + * during renderFeature() and rendered on stopRender(). + */ +class CORE_EXPORT QgsMaskRendererV2 : public QgsFeatureRendererV2 +{ + public: + + /** Constructor + * @param embeddedRenderer optional embeddedRenderer. If null, a default one will be assigned + */ + QgsMaskRendererV2( const QgsFeatureRendererV2* embeddedRenderer = 0 ); + virtual ~QgsMaskRendererV2(); + + /** Used to clone this feature renderer.*/ + virtual QgsFeatureRendererV2* clone(); + + virtual void startRender( QgsRenderContext& context, const QgsFields& fields ); + + /** Renders a given feature. + * This will here collect features. The actual rendering will be postponed to stopRender() + * @param feature the feature to render + * @param context the rendering context + * @param layer the symbol layer to render, if that makes sense + * @param selected whether this feature has been selected (this will add decorations) + * @param drawVertexMarker whether this feature has vertex markers (in edit mode usually) + * @returns true if the rendering was ok + */ + virtual bool renderFeature( QgsFeature& feature, QgsRenderContext& context, int layer = -1, bool selected = false, bool drawVertexMarker = false ); + + /** + * The actual rendering will take place here. + * Features collected during renderFeature() are rendered using the embedded feature renderer + */ + virtual void stopRender( QgsRenderContext& context ); + + /** @returns a textual reprensation of the renderer */ + virtual QString dump() const; + + /** Proxy that will call this method on the embedded renderer. */ + virtual QList usedAttributes(); + /** Proxy that will call this method on the embedded renderer. */ + virtual int capabilities(); + /** Proxy that will call this method on the embedded renderer. */ + virtual QgsSymbolV2List symbols(); + /** Proxy that will call this method on the embedded renderer. */ + virtual QgsSymbolV2* symbolForFeature( QgsFeature& feature ); + /** Proxy that will call this method on the embedded renderer. */ + virtual QgsSymbolV2List symbolsForFeature( QgsFeature& feat ); + /** Proxy that will call this method on the embedded renderer. */ + virtual QgsLegendSymbologyList legendSymbologyItems( QSize iconSize ); + /** Proxy that will call this method on the embedded renderer. */ + virtual QgsLegendSymbolList legendSymbolItems( double scaleDenominator = -1, QString rule = "" ); + /** Proxy that will call this method on the embedded renderer. */ + virtual bool willRenderFeature( QgsFeature& feat ); + + /** Creates a renderer out of an XML, for loading*/ + static QgsFeatureRendererV2* create( QDomElement& element ); + + /** Creates an XML representation of the renderer. Used for saving purpose + * @param doc the XML document where to create the XML subtree + * @returns the created XML subtree + */ + virtual QDomElement save( QDomDocument& doc ); + + /** sets the embedded renderer + * @param subRenderer the embedded renderer (will be cloned) + */ + void setEmbeddedRenderer( const QgsFeatureRendererV2* subRenderer ); + /** @returns the current embedded renderer + */ + const QgsFeatureRendererV2* embeddedRenderer() const; + + private: + /** Private copy constructor. @see clone() */ + QgsMaskRendererV2( const QgsMaskRendererV2& ); + /** Private assignment operator. @see clone() */ + QgsMaskRendererV2& operator=( const QgsMaskRendererV2& ); + + /** Embedded renderer */ + QScopedPointer mSubRenderer; + + typedef QMap< QByteArray, QList > FeatureCategoryMap; + /** where features are stored, based on their symbol category */ + FeatureCategoryMap mFeaturesCategoryMap; + + /** fields of each feature*/ + QgsFields mFields; + + /** Class used to represent features that must be rendered + with decorations (selection, vertex markers) + */ + struct FeatureDecoration + { + QgsFeature feature; + bool selected; + bool drawMarkers; + int layer; + FeatureDecoration( QgsFeature& a_feature, bool a_selected, bool a_drawMarkers, int a_layer ) : + feature(a_feature),selected(a_selected), drawMarkers(a_drawMarkers), layer(a_layer) {} + }; + QList mFeatureDecorations; +}; + + +#endif // QGSMASKRENDERERV2_H diff --git a/src/core/symbology-ng/qgsrendererv2registry.cpp b/src/core/symbology-ng/qgsrendererv2registry.cpp index ecce71d22298..0e9a775fc420 100644 --- a/src/core/symbology-ng/qgsrendererv2registry.cpp +++ b/src/core/symbology-ng/qgsrendererv2registry.cpp @@ -20,6 +20,7 @@ #include "qgsgraduatedsymbolrendererv2.h" #include "qgsrulebasedrendererv2.h" #include "qgspointdisplacementrenderer.h" +#include "qgsmaskrendererv2.h" QgsRendererV2Registry::QgsRendererV2Registry() { @@ -44,6 +45,10 @@ QgsRendererV2Registry::QgsRendererV2Registry() addRenderer( new QgsRendererV2Metadata( "pointDisplacement", QObject::tr( "Point displacement" ), QgsPointDisplacementRenderer::create ) ); + + addRenderer( new QgsRendererV2Metadata( "maskRenderer", + QObject::tr( "Mask" ), + QgsMaskRendererV2::create ) ); } QgsRendererV2Registry::~QgsRendererV2Registry() diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index dcfcde2989e4..84e0cae8644a 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -20,6 +20,7 @@ symbology-ng/qgssinglesymbolrendererv2widget.cpp symbology-ng/qgscategorizedsymbolrendererv2widget.cpp symbology-ng/qgsgraduatedsymbolrendererv2widget.cpp symbology-ng/qgsrulebasedrendererv2widget.cpp +symbology-ng/qgsmaskrendererv2widget.cpp symbology-ng/qgsrendererv2propertiesdialog.cpp symbology-ng/qgsstylev2managerdialog.cpp symbology-ng/qgssymbollevelsv2dialog.cpp @@ -180,6 +181,7 @@ symbology-ng/qgscategorizedsymbolrendererv2widget.h symbology-ng/qgsdatadefinedsymboldialog.h symbology-ng/qgsgraduatedsymbolrendererv2widget.h symbology-ng/qgsrulebasedrendererv2widget.h +symbology-ng/qgsmaskrendererv2widget.h symbology-ng/qgsrendererv2widget.h symbology-ng/qgsrendererv2propertiesdialog.h symbology-ng/qgsstylev2managerdialog.h diff --git a/src/gui/symbology-ng/qgsmaskrendererv2widget.cpp b/src/gui/symbology-ng/qgsmaskrendererv2widget.cpp new file mode 100644 index 000000000000..6072d8260f93 --- /dev/null +++ b/src/gui/symbology-ng/qgsmaskrendererv2widget.cpp @@ -0,0 +1,124 @@ +/*************************************************************************** + qgsmaskrendererv2widget.cpp + --------------------- + begin : April 2014 + copyright : (C) 2014 Hugo Mercier / Oslandia + email : hugo dot mercier at oslandia dot com + *************************************************************************** + * * + * 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 "qgsmaskrendererv2widget.h" +#include "qgsmaskrendererv2.h" +#include "qgsrendererv2registry.h" + +#include "qgssymbolv2.h" + +#include "qgslogger.h" +#include "qgsvectorlayer.h" + +QgsRendererV2Widget* QgsMaskRendererV2Widget::create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ) +{ + return new QgsMaskRendererV2Widget( layer, style, renderer ); +} + +QgsMaskRendererV2Widget::QgsMaskRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ) + : QgsRendererV2Widget( layer, style ) +{ + if ( !layer ) { + return; + } + + // the renderer only applies to polygon vector layers + if ( layer->wkbType() != QGis::WKBPolygon && + layer->wkbType() != QGis::WKBPolygon25D && + layer->wkbType() != QGis::WKBMultiPolygon && + layer->wkbType() != QGis::WKBMultiPolygon25D ) + { + //setup blank dialog + mRenderer.reset( 0 ); + QGridLayout* layout = new QGridLayout( this ); + QLabel* label = new QLabel( tr( "The mask renderer only applies to polygon and multipolygon layers. \n" + "'%1' is not a polygon layer and then cannot be displayed" ) + .arg( layer->name() ), this ); + layout->addWidget( label ); + return; + } + setupUi( this ); + + // try to recognize the previous renderer + // (null renderer means "no previous renderer") + if ( !renderer || renderer->type() != "maskRenderer" ) + { + mRenderer.reset( new QgsMaskRendererV2() ); + } + else + { + mRenderer.reset( static_cast( renderer ) ); + } + + int currentEmbeddedIdx = 0; + //insert possible renderer types + QStringList rendererList = QgsRendererV2Registry::instance()->renderersList(); + QStringList::const_iterator it = rendererList.constBegin(); + int idx = 0; + mRendererComboBox->blockSignals( true ); + for ( ; it != rendererList.constEnd(); ++it, ++idx ) + { + if (( *it != "maskRenderer" ) && //< a mask renderer cannot contain another mask renderer + ( *it != "pointDisplacement" )) //< a mask renderer can only contain a polygon renderer + { + QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( *it ); + mRendererComboBox->addItem( m->icon(), m->visibleName(), /* data */ *it ); + const QgsFeatureRendererV2* embeddedRenderer = mRenderer->embeddedRenderer(); + if ( embeddedRenderer && embeddedRenderer->type() == m->name() ) + { + // store the combo box index of the current renderer + currentEmbeddedIdx = idx; + } + } + } + mRendererComboBox->blockSignals( false ); + + int oldIdx = mRendererComboBox->currentIndex(); + mRendererComboBox->setCurrentIndex( currentEmbeddedIdx ); + if ( oldIdx == currentEmbeddedIdx ) + { + // force update + on_mRendererComboBox_currentIndexChanged( currentEmbeddedIdx ); + } +} + +QgsFeatureRendererV2* QgsMaskRendererV2Widget::renderer() +{ + if ( mRenderer && mEmbeddedRendererWidget ) + { + QgsFeatureRendererV2* embeddedRenderer = mEmbeddedRendererWidget->renderer(); + if ( embeddedRenderer ) + { + mRenderer->setEmbeddedRenderer( embeddedRenderer->clone() ); + } + } + return mRenderer.data(); +} + +void QgsMaskRendererV2Widget::on_mRendererComboBox_currentIndexChanged( int index ) +{ + QString rendererId = mRendererComboBox->itemData( index ).toString(); + QgsRendererV2AbstractMetadata* m = QgsRendererV2Registry::instance()->rendererMetadata( rendererId ); + if ( m ) + { + mEmbeddedRendererWidget.reset( m->createRendererWidget( mLayer, mStyle, const_cast(mRenderer->embeddedRenderer())->clone() ) ); + + if ( mLayout->count() > 1 ) { + // remove the current renderer widget + mLayout->takeAt( 1 ); + } + mLayout->addWidget( mEmbeddedRendererWidget.data() ); + } +} + diff --git a/src/gui/symbology-ng/qgsmaskrendererv2widget.h b/src/gui/symbology-ng/qgsmaskrendererv2widget.h new file mode 100644 index 000000000000..983d101f5fe0 --- /dev/null +++ b/src/gui/symbology-ng/qgsmaskrendererv2widget.h @@ -0,0 +1,60 @@ +/*************************************************************************** + qgsmaskrendererv2widget.h + --------------------- + begin : April 2014 + copyright : (C) 2014 Hugo Mercier / Oslandia + email : hugo dot mercier at oslandia dot com + *************************************************************************** + * * + * 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 QGSMASKRENDERERV2WIDGET_H +#define QGSMASKRENDERERV2WIDGET_H + +#include "ui_qgsmaskrendererwidgetbase.h" +#include "qgsmaskrendererv2.h" +#include "qgsrendererv2widget.h" + +class QMenu; + +/** + * A widget used represent options of a QgsMaskRendererV2 + */ +class GUI_EXPORT QgsMaskRendererV2Widget : public QgsRendererV2Widget, private Ui::QgsMaskRendererWidgetBase +{ + Q_OBJECT + + public: + /** static creation method + * @param layer the layer where this renderer is applied + * @param style + * @param renderer the mask renderer (will take ownership) + */ + static QgsRendererV2Widget* create( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ); + + /** Constructor + * @param layer the layer where this renderer is applied + * @param style + * @param renderer the mask renderer (will take ownership) + */ + QgsMaskRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer ); + + /** @returns the current feature renderer */ + virtual QgsFeatureRendererV2* renderer(); + + protected: + /** the mask renderer */ + QScopedPointer mRenderer; + /** the widget used to represent the mask's embedded renderer */ + QScopedPointer mEmbeddedRendererWidget; + + private slots: + void on_mRendererComboBox_currentIndexChanged( int index ); +}; + + +#endif // QGSMASKRENDERERV2WIDGET_H diff --git a/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp b/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp index 346a8a316d84..3906ff08c491 100644 --- a/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp +++ b/src/gui/symbology-ng/qgsrendererv2propertiesdialog.cpp @@ -23,6 +23,7 @@ #include "qgsgraduatedsymbolrendererv2widget.h" #include "qgsrulebasedrendererv2widget.h" #include "qgspointdisplacementrendererwidget.h" +#include "qgsmaskrendererv2widget.h" #include "qgsapplication.h" #include "qgslogger.h" @@ -66,6 +67,7 @@ static void _initRendererWidgetFunctions() _initRenderer( "graduatedSymbol", QgsGraduatedSymbolRendererV2Widget::create, "rendererGraduatedSymbol.png" ); _initRenderer( "RuleRenderer", QgsRuleBasedRendererV2Widget::create ); _initRenderer( "pointDisplacement", QgsPointDisplacementRendererWidget::create ); + _initRenderer( "maskRenderer", QgsMaskRendererV2Widget::create ); initialized = true; }