Ensure expression context is available to expression builders

called from field expression widgets
This commit is contained in:
Nyall Dawson 2015-08-20 10:50:38 +10:00
parent 1c1e574d64
commit be26c61bc4
16 changed files with 213 additions and 20 deletions

View File

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

View File

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

View File

@ -90,12 +90,26 @@ 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 );
@ -103,6 +117,7 @@ QWidget* QgsComposerColumnSourceDelegate::createEditor( QWidget* parent, const Q
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 );

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -379,6 +379,19 @@ QgsRendererV2Widget* QgsGraduatedSymbolRendererV2Widget::create( QgsVectorLayer*
return new QgsGraduatedSymbolRendererV2Widget( 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;
}
QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
: QgsRendererV2Widget( layer, style )
, mRenderer( 0 )
@ -472,6 +485,8 @@ QgsGraduatedSymbolRendererV2Widget::QgsGraduatedSymbolRendererV2Widget( QgsVecto
mHistogramWidget->setRenderer( mRenderer );
connect( mHistogramWidget, SIGNAL( rangesModified( bool ) ), this, SLOT( refreshRanges( bool ) ) );
connect( mExpressionWidget, SIGNAL( fieldChanged( QString ) ), mHistogramWidget, SLOT( setSourceFieldExp( QString ) ) );
mExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );
}
void QgsGraduatedSymbolRendererV2Widget::on_mSizeUnitWidget_changed()

View File

@ -31,6 +31,19 @@ QgsRendererV2Widget* QgsHeatmapRendererWidget::create( QgsVectorLayer* layer, Qg
return new QgsHeatmapRendererWidget( 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;
}
QgsHeatmapRendererWidget::QgsHeatmapRendererWidget( QgsVectorLayer* layer, QgsStyleV2* style, QgsFeatureRendererV2* renderer )
: QgsRendererV2Widget( layer, style )
, mRenderer( NULL )
@ -54,6 +67,7 @@ QgsHeatmapRendererWidget::QgsHeatmapRendererWidget( QgsVectorLayer* layer, QgsSt
setupUi( this );
mRadiusUnitWidget->setUnits( QgsSymbolV2::OutputUnitList() << QgsSymbolV2::MM << QgsSymbolV2::Pixel << QgsSymbolV2::MapUnit );
mWeightExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );
if ( renderer )
{

View File

@ -78,6 +78,19 @@ void QgsSizeScaleWidget::setFromSymbol()
updatePreview();
}
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;
}
QgsSizeScaleWidget::QgsSizeScaleWidget( const QgsVectorLayer * layer, const QgsMarkerSymbolV2 * symbol )
: mSymbol( symbol )
// we just use the minimumValue and maximumValue from the layer, unfortunately they are
@ -87,6 +100,8 @@ QgsSizeScaleWidget::QgsSizeScaleWidget( const QgsVectorLayer * layer, const QgsM
setupUi( this );
setWindowFlags( Qt::WindowStaysOnTopHint );
mExpressionWidget->registerGetExpressionContextCallback( &_getExpressionContext, mLayer );
if ( mLayer )
{
mLayerTreeLayer = new QgsLayerTreeLayer( mLayer );