Skip to content
Permalink
Browse files

Ensure expression context is available to expression builders

called from field expression widgets
  • Loading branch information
nyalldawson committed Aug 22, 2015
1 parent 1c1e574 commit be26c61bc4ad5f0fd75178291b2ac16f8b87d041
@@ -49,6 +49,18 @@ class QgsFieldExpressionWidget : QWidget
//! Returns the currently used layer
QgsVectorLayer* layer() const;

//! Callback function for retrieving the expression context for the expression
//typedef QgsExpressionContext( *ExpressionContextCallback )( const void* context );

/** Register callback function for retrieving the expression context for the expression
* @param fnGetExpressionContext call back function, will be called when the widget requires
* the current expression context
* @param context context for callback function
* @note added in QGIS 2.12
* @note not available in Python bindings
*/
//void registerGetExpressionContextCallback( ExpressionContextCallback fnGetExpressionContext, const void* context );

signals:
//! the signal is emitted when the currently selected field changes
void fieldChanged( QString fieldName );
@@ -25,6 +25,18 @@
#include "qgsexpressionbuilderdialog.h"
#include "qgscomposermap.h"

static QgsExpressionContext _getExpressionContext( const void* context )
{
const QgsComposition* composition = ( const QgsComposition* ) context;
if ( !composition )
{
return QgsExpressionContext();
}

QScopedPointer< QgsExpressionContext > expContext( composition->createExpressionContext() );
return QgsExpressionContext( *expContext );
}

QgsAtlasCompositionWidget::QgsAtlasCompositionWidget( QWidget* parent, QgsComposition* c ):
QWidget( parent ), mComposition( c )
{
@@ -42,6 +54,8 @@ QgsAtlasCompositionWidget::QgsAtlasCompositionWidget( QWidget* parent, QgsCompos
// connect to updates
connect( &mComposition->atlasComposition(), SIGNAL( parameterChanged() ), this, SLOT( updateGuiElements() ) );

mPageNameWidget->registerGetExpressionContextCallback( &_getExpressionContext, mComposition );

updateGuiElements();
}

@@ -90,19 +90,34 @@ void QgsComposerColumnAlignmentDelegate::updateEditorGeometry( QWidget* editor,

// QgsComposerColumnSourceDelegate

QgsComposerColumnSourceDelegate::QgsComposerColumnSourceDelegate( QgsVectorLayer* vlayer, QObject* parent ) : QItemDelegate( parent ),
mVectorLayer( vlayer )
QgsComposerColumnSourceDelegate::QgsComposerColumnSourceDelegate( QgsVectorLayer* vlayer, QObject* parent, const QgsComposerObject* composerObject )
: QItemDelegate( parent )
, mVectorLayer( vlayer )
, mComposerObject( composerObject )
{

}

static QgsExpressionContext _getExpressionContext( const void* context )
{
const QgsComposerObject* object = ( const QgsComposerObject* ) context;
if ( !object )
{
return QgsExpressionContext();
}

QScopedPointer< QgsExpressionContext > expContext( object->createExpressionContext() );
return QgsExpressionContext( *expContext );
}

QWidget* QgsComposerColumnSourceDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
Q_UNUSED( option );
Q_UNUSED( index );

QgsFieldExpressionWidget *fieldExpression = new QgsFieldExpressionWidget( parent );
fieldExpression->setLayer( mVectorLayer );
fieldExpression->registerGetExpressionContextCallback( &_getExpressionContext, mComposerObject );

//listen out for field changes
connect( fieldExpression, SIGNAL( fieldChanged( QString ) ), this, SLOT( commitAndCloseEditor() ) );
@@ -281,7 +296,7 @@ QgsAttributeSelectionDialog::QgsAttributeSelectionDialog( QgsComposerAttributeTa
mColumnsTableView->setModel( mColumnModel );
mColumnsTableView->horizontalHeader()->setResizeMode( QHeaderView::Stretch );

mColumnSourceDelegate = new QgsComposerColumnSourceDelegate( vLayer, mColumnsTableView );
mColumnSourceDelegate = new QgsComposerColumnSourceDelegate( vLayer, mColumnsTableView, mComposerTable );
mColumnsTableView->setItemDelegateForColumn( 0, mColumnSourceDelegate );
mColumnAlignmentDelegate = new QgsComposerColumnAlignmentDelegate( mColumnsTableView );
mColumnsTableView->setItemDelegateForColumn( 2, mColumnAlignmentDelegate );
@@ -336,7 +351,7 @@ QgsAttributeSelectionDialog::QgsAttributeSelectionDialog( QgsComposerAttributeTa
mColumnsTableView->setModel( mColumnModelV1 );
mColumnsTableView->horizontalHeader()->setResizeMode( QHeaderView::Stretch );

mColumnSourceDelegate = new QgsComposerColumnSourceDelegate( vLayer, mColumnsTableView );
mColumnSourceDelegate = new QgsComposerColumnSourceDelegate( vLayer, mColumnsTableView, mComposerTableV1 );
mColumnsTableView->setItemDelegateForColumn( 0, mColumnSourceDelegate );
mColumnAlignmentDelegate = new QgsComposerColumnAlignmentDelegate( mColumnsTableView );
mColumnsTableView->setItemDelegateForColumn( 2, mColumnAlignmentDelegate );
@@ -34,6 +34,7 @@ class QgsComposerAttributeTableColumnModelV2;
class QgsComposerTableSortColumnsProxyModel;
class QgsComposerTableSortColumnsProxyModelV2;
class QgsComposerTableAvailableSortProxyModelV2;
class QgsComposerObject;

// QgsComposerColumnAlignmentDelegate

@@ -60,7 +61,7 @@ class QgsComposerColumnSourceDelegate : public QItemDelegate
Q_OBJECT

public:
QgsComposerColumnSourceDelegate( QgsVectorLayer* vlayer, QObject *parent = 0 );
QgsComposerColumnSourceDelegate( QgsVectorLayer* vlayer, QObject *parent = 0, const QgsComposerObject* composerObject = 0 );
QWidget *createEditor( QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index ) const override;
void setEditorData( QWidget *editor, const QModelIndex &index ) const override;
void setModelData( QWidget *editor, QAbstractItemModel *model, const QModelIndex &index ) const override;
@@ -69,6 +70,7 @@ class QgsComposerColumnSourceDelegate : public QItemDelegate
void commitAndCloseEditor();
private:
QgsVectorLayer* mVectorLayer;
const QgsComposerObject* mComposerObject;
};

// QgsComposerColumnWidthDelegate
@@ -61,6 +61,19 @@ class QgsAttributeTableDock : public QDockWidget
}
};

static QgsExpressionContext _getExpressionContext( const void* context )
{
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope();

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

return expContext;
}

QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWidget *parent, Qt::WindowFlags flags )
: QDialog( parent, flags )
, mDock( 0 )
@@ -222,6 +235,8 @@ QgsAttributeTableDialog::QgsAttributeTableDialog( QgsVectorLayer *theLayer, QWid
break;
}

mUpdateExpressionText->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );

mFieldModel = new QgsFieldModel();
mFieldModel->setLayer( mLayer );
mFieldCombo->setModel( mFieldModel );
@@ -36,11 +36,23 @@
#include <QMessageBox>
#include <QSettings>

static QgsExpressionContext _getExpressionContext( const void* context )
{
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope();

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

return expContext;
}

QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer* layer, QWidget* parent )
: QWidget( parent )
{
mLayer = layer;

if ( !layer )
{
return;
@@ -55,6 +67,7 @@ QgsDiagramProperties::QgsDiagramProperties( QgsVectorLayer* layer, QWidget* pare
connect( mEnableDiagramsCheckBox, SIGNAL( toggled( bool ) ), mDiagramFrame, SLOT( setEnabled( bool ) ) );

mScaleRangeWidget->setMapCanvas( QgisApp::instance()->mapCanvas() );
mSizeFieldExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );

mBackgroundColorButton->setColorDialogTitle( tr( "Select background color" ) );
mBackgroundColorButton->setAllowAlpha( true );
@@ -38,6 +38,18 @@
#include <QCheckBox>
#include <QSettings>

static QgsExpressionContext _getExpressionContext( const void* context )
{
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope();

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

return expContext;
}

QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas, QWidget* parent )
: QWidget( parent )
@@ -58,6 +70,9 @@ QgsLabelingGui::QgsLabelingGui( QgsVectorLayer* layer, QgsMapCanvas* mapCanvas,
return;

setupUi( this );

mFieldExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );

mFontSizeUnitWidget->setUnits( QStringList() << tr( "Points" ) << tr( "Map unit" ), 1 );
mBufferUnitWidget->setUnits( QgsSymbolV2::OutputUnitList() << QgsSymbolV2::MM << QgsSymbolV2::MapUnit );
mShapeSizeUnitWidget->setUnits( QgsSymbolV2::OutputUnitList() << QgsSymbolV2::MM << QgsSymbolV2::MapUnit );
@@ -872,19 +887,6 @@ void QgsLabelingGui::setDataDefinedProperty( const QgsDataDefinedButton* ddBtn,
lyr.setDataDefinedProperty( p, map.value( "active" ).toInt(), map.value( "useexpr" ).toInt(), map.value( "expression" ), map.value( "field" ) );
}

static QgsExpressionContext _getExpressionContext( const void* context )
{
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope();

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

return expContext;
}

void QgsLabelingGui::populateDataDefinedButtons( QgsPalLayerSettings& s )
{
Q_FOREACH ( QgsDataDefinedButton* button, findChildren< QgsDataDefinedButton* >() )
@@ -38,12 +38,29 @@ QList< QgsStatisticalSummary::Statistic > QgsStatisticalSummaryDockWidget::mDisp

#define MISSING_VALUES -1

static QgsExpressionContext _getExpressionContext( const void* context )
{
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope();

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

return expContext;
}

QgsStatisticalSummaryDockWidget::QgsStatisticalSummaryDockWidget( QWidget *parent )
: QDockWidget( parent )
, mLayer( 0 )
{
setupUi( this );

mFieldExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, this );

mLayerComboBox->setFilters( QgsMapLayerProxyModel::VectorLayer );
mFieldExpressionWidget->setFilters( QgsFieldProxyModel::Numeric );

@@ -38,6 +38,11 @@ class APP_EXPORT QgsStatisticalSummaryDockWidget : public QDockWidget, private U
QgsStatisticalSummaryDockWidget( QWidget *parent = 0 );
~QgsStatisticalSummaryDockWidget();

/** Returns the currently active layer for the widget
* @note added in QGIS 2.12
*/
QgsVectorLayer* layer() const { return mLayer; }

public slots:

/** Recalculates the displayed statistics
@@ -22,12 +22,27 @@
#include "qgsvectorlayer.h"
#include "qgsexpressionbuilderdialog.h"

static QgsExpressionContext _getExpressionContext( const void* context )
{
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope();

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

return expContext;
}

QgsRelationReferenceConfigDlg::QgsRelationReferenceConfigDlg( QgsVectorLayer* vl, int fieldIdx, QWidget* parent )
: QgsEditorConfigWidget( vl, fieldIdx, parent )
, mReferencedLayer( 0 )
{
setupUi( this );

mExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, vl );

connect( mComboRelation, SIGNAL( currentIndexChanged( int ) ), this, SLOT( relationChanged( int ) ) );

foreach ( const QgsRelation& relation, vl->referencingRelations( fieldIdx ) )
@@ -26,6 +26,8 @@ QgsFieldExpressionWidget::QgsFieldExpressionWidget( QWidget *parent )
: QWidget( parent )
, mExpressionDialogTitle( tr( "Expression dialog" ) )
, mDa( 0 )
, mExpressionContextCallback( 0 )
, mExpressionContextCallbackContext( 0 )
{
QHBoxLayout* layout = new QHBoxLayout( this );
layout->setContentsMargins( 0, 0, 0, 0 );
@@ -127,6 +129,12 @@ QgsVectorLayer *QgsFieldExpressionWidget::layer() const
return mFieldProxyModel->sourceFieldModel()->layer();
}

void QgsFieldExpressionWidget::registerGetExpressionContextCallback( QgsFieldExpressionWidget::ExpressionContextCallback fnGetExpressionContext, const void *context )
{
mExpressionContextCallback = fnGetExpressionContext;
mExpressionContextCallbackContext = context;
}

void QgsFieldExpressionWidget::setLayer( QgsMapLayer *layer )
{
QgsVectorLayer* vl = dynamic_cast<QgsVectorLayer*>( layer );
@@ -180,7 +188,9 @@ void QgsFieldExpressionWidget::editExpression()
QString currentExpression = currentText();
QgsVectorLayer* vl = layer();

QgsExpressionBuilderDialog dlg( vl, currentExpression );
QgsExpressionContext context = mExpressionContextCallback ? mExpressionContextCallback( mExpressionContextCallbackContext ) : *mExpressionContext;

QgsExpressionBuilderDialog dlg( vl, currentExpression, this, "generic", context );
if ( !mDa.isNull() )
{
dlg.setGeomCalculator( *mDa );
@@ -88,6 +88,18 @@ class GUI_EXPORT QgsFieldExpressionWidget : public QWidget
//! Returns the currently used layer
QgsVectorLayer* layer() const;

//! Callback function for retrieving the expression context for the expression
typedef QgsExpressionContext( *ExpressionContextCallback )( const void* context );

/** Register callback function for retrieving the expression context for the expression
* @param fnGetExpressionContext call back function, will be called when the widget requires
* the current expression context
* @param context context for callback function
* @note added in QGIS 2.12
* @note not available in Python bindings
*/
void registerGetExpressionContextCallback( ExpressionContextCallback fnGetExpressionContext, const void* context );

signals:
//! the signal is emitted when the currently selected field changes
void fieldChanged( QString fieldName );
@@ -138,6 +150,8 @@ class GUI_EXPORT QgsFieldExpressionWidget : public QWidget
QString mExpressionDialogTitle;
QSharedPointer<const QgsDistanceArea> mDa;
QScopedPointer< QgsExpressionContext > mExpressionContext;
ExpressionContextCallback mExpressionContextCallback;
const void* mExpressionContextCallbackContext;
};

#endif // QGSFIELDEXPRESSIONWIDGET_H
@@ -370,6 +370,19 @@ QgsRendererV2Widget* QgsCategorizedSymbolRendererV2Widget::create( QgsVectorLaye
return new QgsCategorizedSymbolRendererV2Widget( layer, style, renderer );
}

static QgsExpressionContext _getExpressionContext( const void* context )
{
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope();

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

return expContext;
}

QgsCategorizedSymbolRendererV2Widget::QgsCategorizedSymbolRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
: QgsRendererV2Widget( layer, style )
, mRenderer( 0 )
@@ -451,6 +464,8 @@ QgsCategorizedSymbolRendererV2Widget::QgsCategorizedSymbolRendererV2Widget( QgsV
advMenu->addAction( tr( "Symbol levels..." ), this, SLOT( showSymbolLevels() ) );

btnAdvanced->setMenu( advMenu );

mExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, layer );
}

QgsCategorizedSymbolRendererV2Widget::~QgsCategorizedSymbolRendererV2Widget()

0 comments on commit be26c61

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