Skip to content
Permalink
Browse files

Allow setting expression context for symbol widgets and dialogs

This means that symbol selectors can be aware of the correct variable
scope and values for both populating expression builder widgets and
for symbol previews.
  • Loading branch information
nyalldawson committed Sep 3, 2015
1 parent ffd82a3 commit 096d46464d2735c39b8e376275a4858796507297
@@ -112,7 +112,11 @@ class QgsSymbolV2
//! Generate symbol as image
QImage asImage( QSize size, QgsRenderContext* customContext = 0 );

QImage bigSymbolPreviewImage();
/** Returns a large (roughly 100x100 pixel) preview image for the symbol.
* @param expressionContext optional expression context, for evaluation of
* data defined symbol properties
*/
QImage bigSymbolPreviewImage( QgsExpressionContext* expressionContext = 0 );

QString dump() const;

@@ -7,10 +7,28 @@ class QgsLayerPropertiesWidget : QWidget
public:
QgsLayerPropertiesWidget( QgsSymbolLayerV2* layer, const QgsSymbolV2* symbol, const QgsVectorLayer* vl, QWidget* parent /TransferThis/ = NULL );

/** Returns the expression context used for the widget, if set. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the properties widget.
* @note added in QGIS 2.12
* @see setExpressionContext()
*/
QgsExpressionContext* expressionContext() const;

public slots:
void layerTypeChanged();
void emitSignalChanged();

/** Sets the optional expression context used for the widget. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the properties widget.
* @param context expression context pointer. Ownership is not transferred and the object must
* be kept alive for the lifetime of the properties widget.
* @note added in QGIS 2.12
* @see expressionContext()
*/
void setExpressionContext( QgsExpressionContext* context );

signals:
void changed();
void changeLayer( QgsSymbolLayerV2* );
@@ -11,6 +11,32 @@ class QgsSymbolLayerV2Widget : QWidget
virtual void setSymbolLayer( QgsSymbolLayerV2* layer ) = 0;
virtual QgsSymbolLayerV2* symbolLayer() = 0;


/** Returns the expression context used for the widget, if set. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the layer widget.
* @note added in QGIS 2.12
* @see setExpressionContext()
*/
QgsExpressionContext* expressionContext() const;

/** Returns the vector layer associated with the widget.
* @note added in QGIS 2.12
*/
const QgsVectorLayer* vectorLayer() const;

public slots:

/** Sets the optional expression context used for the widget. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the layer widget.
* @param context expression context pointer. Ownership is not transferred and the object must
* be kept alive for the lifetime of the layer widget.
* @note added in QGIS 2.12
* @see expressionContext()
*/
void setExpressionContext( QgsExpressionContext* context );

protected:

void registerDataDefinedButton( QgsDataDefinedButton * button, const QString & propertyName, QgsDataDefinedButton::DataType type, const QString & description );
@@ -6,6 +6,19 @@ class QgsSymbolsListWidget : QWidget
public:
QgsSymbolsListWidget( QgsSymbolV2* symbol, QgsStyleV2* style, QMenu* menu, QWidget* parent /TransferThis/ = 0, const QgsVectorLayer * layer = 0 );

/** Returns the expression context used for the widget, if set. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the list widget.
* @note added in QGIS 2.12
* @see setExpressionContext()
*/
QgsExpressionContext* expressionContext() const;

/** Returns the vector layer associated with the widget.
* @note added in QGIS 2.12
*/
const QgsVectorLayer* layer() const;

public slots:
void setSymbolFromStyle( const QModelIndex & index );
void setSymbolColor( const QColor& color );
@@ -10,6 +10,23 @@ class QgsSymbolV2SelectorDialog : QDialog
//! return menu for "advanced" button - create it if doesn't exist and show the advanced button
QMenu* advancedMenu();

/** Sets the optional expression context used for the widget. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the layer widget.
* @param context expression context pointer. Ownership is transferred to the dialog.
* @note added in QGIS 2.12
* @see expressionContext()
*/
void setExpressionContext( QgsExpressionContext* context /Transfer/ );

/** Returns the expression context used for the dialog, if set. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the dialog.
* @note added in QGIS 2.12
* @see setExpressionContext()
*/
QgsExpressionContext* expressionContext() const;

protected:
//! Reimplements dialog keyPress event so we can ignore it
void keyPressEvent( QKeyEvent * event );
@@ -311,6 +311,7 @@ void QgsComposerArrowWidget::on_mLineStyleButton_clicked()

QgsLineSymbolV2* newSymbol = dynamic_cast<QgsLineSymbolV2*>( mArrow->lineSymbol()->clone() );
QgsSymbolV2SelectorDialog d( newSymbol, QgsStyleV2::defaultStyle(), 0, this );
d.setExpressionContext( mArrow->createExpressionContext() );

if ( d.exec() == QDialog::Accepted )
{
@@ -109,6 +109,7 @@ void QgsComposerShapeWidget::on_mShapeStyleButton_clicked()

QgsFillSymbolV2* newSymbol = dynamic_cast<QgsFillSymbolV2*>( mComposerShape->shapeStyleSymbol()->clone() );
QgsSymbolV2SelectorDialog d( newSymbol, QgsStyleV2::defaultStyle(), coverageLayer, this );
d.setExpressionContext( mComposerShape->createExpressionContext() );

if ( d.exec() == QDialog::Accepted )
{
@@ -557,6 +557,7 @@ void QgsCompositionWidget::on_mPageStyleButton_clicked()
newSymbol = new QgsFillSymbolV2();
}
QgsSymbolV2SelectorDialog d( newSymbol, QgsStyleV2::defaultStyle(), coverageLayer, this );
d.setExpressionContext( mComposition->createExpressionContext() );

if ( d.exec() == QDialog::Accepted )
{
@@ -387,7 +387,7 @@ QImage QgsSymbolV2::asImage( QSize size, QgsRenderContext* customContext )
}


QImage QgsSymbolV2::bigSymbolPreviewImage()
QImage QgsSymbolV2::bigSymbolPreviewImage( QgsExpressionContext* expressionContext )
{
QImage preview( QSize( 100, 100 ), QImage::Format_ARGB32_Premultiplied );
preview.fill( 0 );
@@ -404,6 +404,9 @@ QImage QgsSymbolV2::bigSymbolPreviewImage()
}

QgsRenderContext context = QgsSymbolLayerV2Utils::createRenderContext( &p );
if ( expressionContext )
context.setExpressionContext( *expressionContext );

startRender( context );

if ( mType == QgsSymbolV2::Line )
@@ -160,7 +160,11 @@ class CORE_EXPORT QgsSymbolV2
//! Generate symbol as image
QImage asImage( QSize size, QgsRenderContext* customContext = 0 );

QImage bigSymbolPreviewImage();
/** Returns a large (roughly 100x100 pixel) preview image for the symbol.
* @param expressionContext optional expression context, for evaluation of
* data defined symbol properties
*/
QImage bigSymbolPreviewImage( QgsExpressionContext* expressionContext = 0 );

QString dump() const;

@@ -82,6 +82,7 @@ static void _initWidgetFunctions()

QgsLayerPropertiesWidget::QgsLayerPropertiesWidget( QgsSymbolLayerV2* layer, const QgsSymbolV2* symbol, const QgsVectorLayer* vl, QWidget* parent )
: QWidget( parent )
, mPresetExpressionContext( 0 )
{

mLayer = layer;
@@ -115,6 +116,15 @@ QgsLayerPropertiesWidget::QgsLayerPropertiesWidget( QgsSymbolLayerV2* layer, con
mEffectWidget->setPaintEffect( mLayer->paintEffect() );
}

void QgsLayerPropertiesWidget::setExpressionContext( QgsExpressionContext *context )
{
mPresetExpressionContext = context;

QgsSymbolLayerV2Widget* w = dynamic_cast< QgsSymbolLayerV2Widget* >( stackedWidget->currentWidget() );
if ( w )
w->setExpressionContext( mPresetExpressionContext );
}

void QgsLayerPropertiesWidget::populateLayerTypes()
{
QStringList types = QgsSymbolLayerV2Registry::instance()->symbolLayersForType( mSymbol->type() );
@@ -154,6 +164,7 @@ void QgsLayerPropertiesWidget::updateSymbolLayerWidget( QgsSymbolLayerV2* layer
if ( w )
{
w->setSymbolLayer( layer );
w->setExpressionContext( mPresetExpressionContext );
stackedWidget->addWidget( w );
stackedWidget->setCurrentWidget( w );
// start receiving updates from widget
@@ -36,10 +36,28 @@ class GUI_EXPORT QgsLayerPropertiesWidget : public QWidget, private Ui::LayerPro
public:
QgsLayerPropertiesWidget( QgsSymbolLayerV2* layer, const QgsSymbolV2* symbol, const QgsVectorLayer* vl, QWidget* parent = NULL );

/** Returns the expression context used for the widget, if set. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the properties widget.
* @note added in QGIS 2.12
* @see setExpressionContext()
*/
QgsExpressionContext* expressionContext() const { return mPresetExpressionContext; }

public slots:
void layerTypeChanged();
void emitSignalChanged();

/** Sets the optional expression context used for the widget. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the properties widget.
* @param context expression context pointer. Ownership is not transferred and the object must
* be kept alive for the lifetime of the properties widget.
* @note added in QGIS 2.12
* @see expressionContext()
*/
void setExpressionContext( QgsExpressionContext* context );

signals:
void changed();
void changeLayer( QgsSymbolLayerV2* );
@@ -53,6 +71,9 @@ class GUI_EXPORT QgsLayerPropertiesWidget : public QWidget, private Ui::LayerPro

const QgsSymbolV2* mSymbol;
const QgsVectorLayer* mVectorLayer;

private:
QgsExpressionContext* mPresetExpressionContext;
};

#endif //QGSLAYERPROPERTIESWIDGET_H
@@ -49,11 +49,16 @@

static QgsExpressionContext _getExpressionContext( const void* context )
{
const QgsSymbolLayerV2Widget* widget = ( const QgsSymbolLayerV2Widget* ) context;

if ( widget->expressionContext() )
return QgsExpressionContext( *widget->expressionContext() );

QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope();

const QgsVectorLayer* layer = ( const QgsVectorLayer* ) context;
const QgsVectorLayer* layer = widget->vectorLayer();
if ( layer )
expContext << QgsExpressionContextUtils::layerScope( layer );

@@ -68,7 +73,7 @@ void QgsSymbolLayerV2Widget::registerDataDefinedButton( QgsDataDefinedButton * b
connect( button, SIGNAL( dataDefinedChanged( const QString& ) ), this, SLOT( updateDataDefinedProperty() ) );
connect( button, SIGNAL( dataDefinedActivated( bool ) ), this, SLOT( updateDataDefinedProperty() ) );

button->registerGetExpressionContextCallback( &_getExpressionContext, const_cast< QgsVectorLayer* >( mVectorLayer ) );
button->registerGetExpressionContextCallback( &_getExpressionContext, this );
}

void QgsSymbolLayerV2Widget::updateDataDefinedProperty()
@@ -29,15 +29,43 @@ class GUI_EXPORT QgsSymbolLayerV2Widget : public QWidget
Q_OBJECT

public:
QgsSymbolLayerV2Widget( QWidget* parent, const QgsVectorLayer* vl = 0 ) : QWidget( parent ), mVectorLayer( vl ) {}
QgsSymbolLayerV2Widget( QWidget* parent, const QgsVectorLayer* vl = 0 ) : QWidget( parent ), mVectorLayer( vl ), mPresetExpressionContext( 0 ) {}
virtual ~QgsSymbolLayerV2Widget() {}

virtual void setSymbolLayer( QgsSymbolLayerV2* layer ) = 0;
virtual QgsSymbolLayerV2* symbolLayer() = 0;

/** Returns the expression context used for the widget, if set. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the layer widget.
* @note added in QGIS 2.12
* @see setExpressionContext()
*/
QgsExpressionContext* expressionContext() const { return mPresetExpressionContext; }

/** Returns the vector layer associated with the widget.
* @note added in QGIS 2.12
*/
const QgsVectorLayer* vectorLayer() const { return mVectorLayer; }

public slots:

/** Sets the optional expression context used for the widget. This expression context is used for
* evaluating data defined symbol properties and for populating based expression widgets in
* the layer widget.
* @param context expression context pointer. Ownership is not transferred and the object must
* be kept alive for the lifetime of the layer widget.
* @note added in QGIS 2.12
* @see expressionContext()
*/
void setExpressionContext( QgsExpressionContext* context ) { mPresetExpressionContext = context; }

protected:
const QgsVectorLayer* mVectorLayer;

//! Optional preset expression context
QgsExpressionContext* mPresetExpressionContext;

void registerDataDefinedButton( QgsDataDefinedButton * button, const QString & propertyName, QgsDataDefinedButton::DataType type, const QString & description );

/** Get label for data defined entry.
@@ -47,6 +47,7 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbolV2* symbol, QgsStyleV2* sty
, mAdvancedMenu( 0 )
, mClipFeaturesAction( 0 )
, mLayer( layer )
, mPresetExpressionContext( 0 )
{
setupUi( this );

@@ -116,6 +117,11 @@ QgsSymbolsListWidget::QgsSymbolsListWidget( QgsSymbolV2* symbol, QgsStyleV2* sty
btnColor->setContext( "symbology" );
}

void QgsSymbolsListWidget::setExpressionContext( QgsExpressionContext *context )
{
mPresetExpressionContext = context;
}

void QgsSymbolsListWidget::populateGroups( QString parent, QString prepend )
{
QgsSymbolGroupMap groups = mStyle->childGroupNames( parent );
@@ -362,11 +368,17 @@ void QgsSymbolsListWidget::updateSymbolColor()

static QgsExpressionContext _getExpressionContext( const void* context )
{
const QgsSymbolsListWidget* widget = ( const QgsSymbolsListWidget* ) context;

if ( widget->expressionContext() )
return QgsExpressionContext( *widget->expressionContext() );

//otherwise create a default symbol context
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope();

const QgsVectorLayer* layer = ( const QgsVectorLayer* ) context;
const QgsVectorLayer* layer = widget->layer();
if ( layer )
expContext << QgsExpressionContextUtils::layerScope( layer );

@@ -379,7 +391,7 @@ void QgsSymbolsListWidget::updateSymbolInfo()

Q_FOREACH ( QgsDataDefinedButton* button, findChildren< QgsDataDefinedButton* >() )
{
button->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );
button->registerGetExpressionContextCallback( &_getExpressionContext, this );
}

if ( mSymbol->type() == QgsSymbolV2::Marker )

0 comments on commit 096d464

Please sign in to comment.
You can’t perform that action at this time.