Switch some composer expressions to contexts

This commit is contained in:
Nyall Dawson 2015-08-13 09:42:51 +10:00
parent f9a78207a7
commit a0e35a3893
15 changed files with 470 additions and 26 deletions

View File

@ -630,6 +630,12 @@ class QgsComposerItem : QgsComposerObject, QGraphicsRectItem
*/
void setCurrentExportLayer( const int layerIdx = -1 );
/** Creates an expression context relating to the item's current state. The context includes
* scopes for global, project, composition, atlas and item properties.
* @note added in QGIS 2.12
*/
QgsExpressionContext* createExpressionContext() const /Factory/;
public slots:
/** Sets the item rotation
* @deprecated Use setItemRotation( double rotation ) instead

View File

@ -404,6 +404,56 @@ class QgsExpressionContextUtils
*/
static void setLayerVariables( QgsMapLayer* layer, const QgsStringMap variables );
/** Creates a new scope which contains variables and functions relating to a QgsComposition.
* For instance, number of pages and page sizes.
* @param composition source composition
*/
static QgsExpressionContextScope* compositionScope( const QgsComposition *composition ) /Factory/;
/** Sets a composition context variable. This variable will be contained within scopes retrieved via
* compositionScope().
* @param composition target composition
* @param name variable name
* @param value variable value
* @see setCompositionVariables()
* @see compositionScope()
*/
static void setCompositionVariable( QgsComposition* composition, const QString& name, const QVariant& value );
/** Sets all composition context variables. Existing composition variables will be removed and replaced
* with the variables specified.
* @param composition target composition
* @param variables new set of layer variables
* @see setCompositionVariable()
* @see compositionScope()
*/
static void setCompositionVariables( QgsComposition* composition, const QgsStringMap variables );
/** Creates a new scope which contains variables and functions relating to a QgsComposerItem.
* For instance, item size and position.
* @param composerItem source composer item
*/
static QgsExpressionContextScope* composerItemScope( const QgsComposerItem *composerItem ) /Factory/;
/** Sets a composer item context variable. This variable will be contained within scopes retrieved via
* composerItemScope().
* @param composerItem target composer item
* @param name variable name
* @param value variable value
* @see setComposerItemVariables()
* @see composerItemScope()
*/
static void setComposerItemVariable( QgsComposerItem* composerItem, const QString& name, const QVariant& value );
/** Sets all composition context variables. Existing compositoin variables will be removed and replaced
* with the variables specified.
* @param composerItem target composer item
* @param variables new set of layer variables
* @see setComposerItemVariable()
* @see composerItemScope()
*/
static void setComposerItemVariables( QgsComposerItem* composerItem, const QgsStringMap variables );
/** Registers all known core functions provided by QgsExpressionContextScope objects.
*/
static void registerContextFunctions();

View File

@ -22,6 +22,7 @@
#include "qgscomposition.h"
#include "qgspoint.h"
#include "qgsdatadefinedbutton.h"
#include "qgsexpressioncontext.h"
#include <QColorDialog>
#include <QPen>
@ -140,6 +141,13 @@ QgsComposerItemWidget::QgsComposerItemWidget( QWidget* parent, QgsComposerItem*
connect( mTransparencySlider, SIGNAL( valueChanged( int ) ), mTransparencySpnBx, SLOT( setValue( int ) ) );
QgsExpressionContext* context = mItem->createExpressionContext();
mVariableEditor->setContext( context );
mVariableEditor->setEditableScopeIndex( context->scopeCount() - 1 );
delete context;
connect( mVariableEditor, SIGNAL( scopeChanged() ), this, SLOT( variablesChanged() ) );
//connect atlas signals to data defined buttons
QgsAtlasComposition* atlas = atlasComposition();
if ( atlas )
@ -260,6 +268,11 @@ void QgsComposerItemWidget::changeItemPosition()
mItem->endCommand();
}
void QgsComposerItemWidget::variablesChanged()
{
QgsExpressionContextUtils::setComposerItemVariables( mItem, mVariableEditor->variablesInActiveScope() );
}
QgsComposerItem::ItemPositionMode QgsComposerItemWidget::positionMode() const
{
if ( mUpperLeftCheckBox->checkState() == Qt::Checked )

View File

@ -139,6 +139,11 @@ class QgsComposerItemWidget: public QgsComposerItemBaseWidget, private Ui::QgsCo
// void changeItemTransparency( int value );
void changeItemPosition();
private slots:
void variablesChanged();
};
#endif //QGSCOMPOSERITEMWIDGET_H

View File

@ -22,6 +22,7 @@
#include "qgsstylev2.h"
#include "qgssymbolv2selectordialog.h"
#include "qgssymbollayerv2utils.h"
#include "qgsexpressioncontext.h"
#include <QColorDialog>
#include <QWidget>
#include <QPrinter> //for screen resolution
@ -44,6 +45,14 @@ QgsCompositionWidget::QgsCompositionWidget( QWidget* parent, QgsComposition* c )
//read with/height from composition and find suitable entries to display
displayCompositionWidthHeight();
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::globalScope() );
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::projectScope() );
mVariableEditor->context()->appendScope( QgsExpressionContextUtils::compositionScope( mComposition ) );
mVariableEditor->reloadContext();
mVariableEditor->setEditableScopeIndex( 2 );
connect( mVariableEditor, SIGNAL( scopeChanged() ), this, SLOT( variablesChanged() ) );
if ( mComposition )
{
mNumPagesSpinBox->setValue( mComposition->numPages() );
@ -170,6 +179,11 @@ void QgsCompositionWidget::populateDataDefinedButtons()
mPaperOrientationDDBtn->blockSignals( false );
}
void QgsCompositionWidget::variablesChanged()
{
QgsExpressionContextUtils::setCompositionVariables( mComposition, mVariableEditor->variablesInActiveScope() );
}
void QgsCompositionWidget::setDataDefinedProperty( const QgsDataDefinedButton* ddBtn, QgsComposerObject::DataDefinedProperty property )
{
if ( !mComposition )

View File

@ -83,6 +83,8 @@ class QgsCompositionWidget: public QWidget, private Ui::QgsCompositionWidgetBase
/** Initializes data defined buttons to current atlas coverage layer*/
void populateDataDefinedButtons();
void variablesChanged();
private:
QgsComposition* mComposition;
QMap<QString, QgsCompositionPaper> mPaperMap;

View File

@ -27,6 +27,7 @@
#include "qgsmaplayerregistry.h"
#include "qgsproject.h"
#include "qgsmessagelog.h"
#include "qgsexpressioncontext.h"
QgsAtlasComposition::QgsAtlasComposition( QgsComposition* composition )
: mComposition( composition )
@ -218,6 +219,8 @@ int QgsAtlasComposition::updateFeatures()
return 0;
}
QgsExpressionContext expressionContext = createExpressionContext();
updateFilenameExpression();
// select all features with all attributes
@ -248,7 +251,7 @@ int QgsAtlasComposition::updateFeatures()
{
nameExpression.reset( 0 );
}
nameExpression->prepare( mCoverageLayer->pendingFields() );
nameExpression->prepare( &expressionContext );
}
// We cannot use nextFeature() directly since the feature pointer is rewinded by the rendering process
@ -260,10 +263,12 @@ int QgsAtlasComposition::updateFeatures()
while ( fit.nextFeature( feat ) )
{
expressionContext.setFeature( feat );
QString pageName;
if ( !nameExpression.isNull() )
{
QVariant result = nameExpression->evaluate( &feat, mCoverageLayer->fields() );
QVariant result = nameExpression->evaluate( &expressionContext );
if ( nameExpression->hasEvalError() )
{
QgsMessageLog::logMessage( tr( "Atlas name eval error: %1" ).arg( nameExpression->evalErrorString() ), tr( "Composer" ) );
@ -446,13 +451,15 @@ bool QgsAtlasComposition::prepareForFeature( const int featureI, const bool upda
// retrieve the next feature, based on its id
mCoverageLayer->getFeatures( QgsFeatureRequest().setFilterFid( mFeatureIds[ featureI ].first ) ).nextFeature( mCurrentFeature );
QgsExpressionContext expressionContext = createExpressionContext();
QgsExpression::setSpecialColumn( "$atlasfeatureid", mCurrentFeature.id() );
QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( *mCurrentFeature.constGeometry() ) );
QgsExpression::setSpecialColumn( "$atlasfeature", QVariant::fromValue( mCurrentFeature ) );
QgsExpression::setSpecialColumn( "$feature", QVariant(( int )featureI + 1 ) );
// generate filename for current feature
if ( !evalFeatureFilename() )
if ( !evalFeatureFilename( expressionContext ) )
{
//error evaluating filename
return false;
@ -820,6 +827,23 @@ bool QgsAtlasComposition::setFilenamePattern( const QString& pattern )
return updateFilenameExpression();
}
QgsExpressionContext QgsAtlasComposition::createExpressionContext()
{
QgsExpressionContext expressionContext;
expressionContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope();
if ( mComposition )
expressionContext << QgsExpressionContextUtils::compositionScope( mComposition );
expressionContext << new QgsExpressionContextScope( "Atlas" );
if ( mCoverageLayer )
expressionContext.lastScope()->setFields( mCoverageLayer->fields() );
if ( mComposition->atlasMode() != QgsComposition::AtlasOff )
expressionContext.lastScope()->setFeature( mCurrentFeature );
return expressionContext;
}
bool QgsAtlasComposition::updateFilenameExpression()
{
if ( !mCoverageLayer )
@ -827,7 +851,7 @@ bool QgsAtlasComposition::updateFilenameExpression()
return false;
}
const QgsFields& fields = mCoverageLayer->fields();
QgsExpressionContext expressionContext = createExpressionContext();
if ( mFilenamePattern.size() > 0 )
{
@ -841,23 +865,23 @@ bool QgsAtlasComposition::updateFilenameExpression()
}
// prepare the filename expression
mFilenameExpr->prepare( fields );
mFilenameExpr->prepare( &expressionContext );
}
//if atlas preview is currently enabled, regenerate filename for current feature
if ( mComposition->atlasMode() == QgsComposition::PreviewAtlas )
{
evalFeatureFilename();
evalFeatureFilename( expressionContext );
}
return true;
}
bool QgsAtlasComposition::evalFeatureFilename()
bool QgsAtlasComposition::evalFeatureFilename( const QgsExpressionContext &context )
{
//generate filename for current atlas feature
if ( mFilenamePattern.size() > 0 && !mFilenameExpr.isNull() )
{
QVariant filenameRes = mFilenameExpr->evaluate( &mCurrentFeature, mCoverageLayer->fields() );
QVariant filenameRes = mFilenameExpr->evaluate( &context );
if ( mFilenameExpr->hasEvalError() )
{
QgsMessageLog::logMessage( tr( "Atlas filename evaluation error: %1" ).arg( mFilenameExpr->evalErrorString() ), tr( "Composer" ) );

View File

@ -29,6 +29,7 @@ class QgsComposerMap;
class QgsComposition;
class QgsVectorLayer;
class QgsExpression;
class QgsExpressionContext;
/** \ingroup MapComposer
* Class used to render an Atlas, iterating over geometry features.
@ -338,7 +339,7 @@ class CORE_EXPORT QgsAtlasComposition : public QObject
/** Evaluates filename for current feature
* @returns true if feature filename was successfully evaluated
*/
bool evalFeatureFilename();
bool evalFeatureFilename( const QgsExpressionContext &context );
QgsComposition* mComposition;
@ -396,6 +397,8 @@ class CORE_EXPORT QgsAtlasComposition : public QObject
//computes the extent of the current feature, in the crs of the specified map
void computeExtent( QgsComposerMap *map );
QgsExpressionContext createExpressionContext();
//list of predefined scales
QVector<qreal> mPredefinedScales;
};

View File

@ -40,6 +40,7 @@
#include "qgslogger.h"
#include "qgssymbollayerv2utils.h" //for pointOnLineWithDistance
#include "qgsmaprenderer.h" //for getCompositionMode
#include "qgsexpressioncontext.h"
#include <cmath>
@ -846,6 +847,24 @@ bool QgsComposerItem::shouldDrawItem() const
return !mEvaluatedExcludeFromExports;
}
QgsExpressionContext* QgsComposerItem::createExpressionContext() const
{
QgsExpressionContext* context = new QgsExpressionContext();
context->appendScope( QgsExpressionContextUtils::globalScope() );
context->appendScope( QgsExpressionContextUtils::projectScope() );
if ( mComposition )
{
context->appendScope( QgsExpressionContextUtils::compositionScope( mComposition ) );
if ( mComposition->atlasComposition().enabled() )
{
context->appendScope( QgsExpressionContextUtils::atlasScope( &mComposition->atlasComposition() ) );
}
}
context->appendScope( QgsExpressionContextUtils::composerItemScope( this ) );
return context;
}
void QgsComposerItem::drawBackground( QPainter* p )
{
if ( mBackground && p )

View File

@ -31,6 +31,7 @@ class QGraphicsLineItem;
class QgsComposerItemGroup;
class QgsDataDefined;
class QgsComposition;
class QgsExpressionContext;
/** \ingroup MapComposer
* A item that forms part of a map composition.
@ -582,6 +583,12 @@ class CORE_EXPORT QgsComposerItem: public QgsComposerObject, public QGraphicsRec
*/
virtual void setCurrentExportLayer( const int layerIdx = -1 ) { mCurrentExportLayer = layerIdx; }
/** Creates an expression context relating to the item's current state. The context includes
* scopes for global, project, composition, atlas and item properties.
* @note added in QGIS 2.12
*/
QgsExpressionContext* createExpressionContext() const;
public slots:
/** Sets the item rotation
* @deprecated Use setItemRotation( double rotation ) instead

View File

@ -25,6 +25,7 @@
#include "qgsproject.h"
#include "qgsdistancearea.h"
#include "qgsfontutils.h"
#include "qgsexpressioncontext.h"
#include "qgswebview.h"
#include "qgswebframe.h"
@ -269,19 +270,16 @@ void QgsComposerLabel::refreshExpressionContext()
if ( !mComposition )
return;
QgsVectorLayer* layer = 0;
if ( mComposition->atlasComposition().enabled() )
{
mExpressionLayer = mComposition->atlasComposition().coverageLayer();
if ( mComposition->atlasMode() != QgsComposition::AtlasOff )
{
mExpressionFeature.reset( new QgsFeature( mComposition->atlasComposition().feature() ) );
}
layer = mComposition->atlasComposition().coverageLayer();
}
//setup distance area conversion
if ( mExpressionLayer )
if ( layer )
{
mDistanceArea->setSourceCrs( mExpressionLayer->crs().srsid() );
mDistanceArea->setSourceCrs( layer->crs().srsid() );
}
else
{
@ -300,7 +298,16 @@ QString QgsComposerLabel::displayText() const
replaceDateText( displayText );
QMap<QString, QVariant> subs = mSubstitutions;
subs[ "$page" ] = QVariant(( int )mComposition->itemPageNumber( this ) + 1 );
return QgsExpression::replaceExpressionText( displayText, mExpressionFeature.data(), mExpressionLayer, &subs, mDistanceArea );
QScopedPointer<QgsExpressionContext> context( createExpressionContext() );
//overwrite layer/feature if they have been set via setExpressionContext
//TODO remove when setExpressionContext is removed
if ( mExpressionFeature.data() )
context->setFeature( *mExpressionFeature.data() );
if ( mExpressionLayer )
context->setFields( mExpressionLayer->fields() );
return QgsExpression::replaceExpressionText( displayText, context.data(), &subs, mDistanceArea );
}
void QgsComposerLabel::replaceDateText( QString& text ) const

View File

@ -22,6 +22,9 @@
#include "qgsproject.h"
#include "qgssymbollayerv2utils.h"
#include "qgsgeometry.h"
#include "qgscomposition.h"
#include "qgscomposeritem.h"
#include "qgsatlascomposition.h"
#include <QSettings>
#include <QDir>
@ -586,6 +589,167 @@ void QgsExpressionContextUtils::setLayerVariables( QgsMapLayer* layer, const Qgs
layer->setCustomProperty( "variableValues", variableValues );
}
QgsExpressionContextScope *QgsExpressionContextUtils::compositionScope( const QgsComposition *composition )
{
QgsExpressionContextScope* scope = new QgsExpressionContextScope( QObject::tr( "Composition" ) );
if ( !composition )
return scope;
//add variables defined in composition properties
QStringList variableNames = composition->customProperty( "variableNames" ).toStringList();
QStringList variableValues = composition->customProperty( "variableValues" ).toStringList();
int varIndex = 0;
foreach ( QString variableName, variableNames )
{
if ( varIndex >= variableValues.length() )
{
break;
}
QVariant varValue = variableValues.at( varIndex );
varIndex++;
scope->setVariable( variableName, varValue );
}
//add known composition context variables
scope->addVariable( QgsExpressionContextScope::StaticVariable( "composer_numpages", composition->numPages(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "composer_page_height", composition->paperHeight(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "composer_page_width", composition->paperWidth(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "composer_dpi", composition->printResolution(), true ) );
return scope;
}
void QgsExpressionContextUtils::setCompositionVariable( QgsComposition* composition, const QString& name, const QVariant& value )
{
if ( !composition )
return;
//write variable to composition
QStringList variableNames = composition->customProperty( "variableNames" ).toStringList();
QStringList variableValues = composition->customProperty( "variableValues" ).toStringList();
variableNames << name;
variableValues << value.toString();
composition->setCustomProperty( "variableNames", variableNames );
composition->setCustomProperty( "variableValues", variableValues );
}
void QgsExpressionContextUtils::setCompositionVariables( QgsComposition* composition, const QgsStringMap variables )
{
if ( !composition )
return;
QStringList variableNames;
QStringList variableValues;
Q_FOREACH ( QString variable, variables.keys() )
{
variableNames << variable;
variableValues << variables.value( variable );
}
composition->setCustomProperty( "variableNames", variableNames );
composition->setCustomProperty( "variableValues", variableValues );
}
QgsExpressionContextScope* QgsExpressionContextUtils::atlasScope( const QgsAtlasComposition* atlas )
{
QgsExpressionContextScope* scope = new QgsExpressionContextScope( QObject::tr( "Atlas" ) );
if ( !atlas )
return scope;
//add known atlas variables
scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_numpages", atlas->numFeatures(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_page", atlas->currentFeatureNumber() + 1, true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_filename", atlas->currentFilename(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_pagename", atlas->currentPageName(), true ) );
if ( atlas->enabled() && atlas->coverageLayer() )
{
scope->setFields( atlas->coverageLayer()->fields() );
}
if ( atlas->enabled() )
{
QgsFeature atlasFeature = atlas->feature();
scope->setFeature( atlasFeature );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "atlas_featureid", atlasFeature.id(), true ) );
}
return scope;
}
QgsExpressionContextScope *QgsExpressionContextUtils::composerItemScope( const QgsComposerItem *composerItem )
{
QgsExpressionContextScope* scope = new QgsExpressionContextScope( QObject::tr( "Composer Item" ) );
if ( !composerItem )
return scope;
//add variables defined in composer item properties
QStringList variableNames = composerItem->customProperty( "variableNames" ).toStringList();
QStringList variableValues = composerItem->customProperty( "variableValues" ).toStringList();
int varIndex = 0;
foreach ( QString variableName, variableNames )
{
if ( varIndex >= variableValues.length() )
{
break;
}
QVariant varValue = variableValues.at( varIndex );
varIndex++;
scope->setVariable( variableName, varValue );
}
//add known composer item context variables
scope->addVariable( QgsExpressionContextScope::StaticVariable( "item_id", composerItem->id(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "item_uuid", composerItem->uuid(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "item_left", composerItem->sceneBoundingRect().left(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "item_top", composerItem->sceneBoundingRect().top(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "item_width", composerItem->sceneBoundingRect().width(), true ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( "item_height", composerItem->sceneBoundingRect().height(), true ) );
return scope;
}
void QgsExpressionContextUtils::setComposerItemVariable( QgsComposerItem* composerItem, const QString& name, const QVariant& value )
{
if ( !composerItem )
return;
//write variable to composer item
QStringList variableNames = composerItem->customProperty( "variableNames" ).toStringList();
QStringList variableValues = composerItem->customProperty( "variableValues" ).toStringList();
variableNames << name;
variableValues << value.toString();
composerItem->setCustomProperty( "variableNames", variableNames );
composerItem->setCustomProperty( "variableValues", variableValues );
}
void QgsExpressionContextUtils::setComposerItemVariables( QgsComposerItem* composerItem, const QgsStringMap variables )
{
if ( !composerItem )
return;
QStringList variableNames;
QStringList variableValues;
Q_FOREACH ( QString variable, variables.keys() )
{
variableNames << variable;
variableValues << variables.value( variable );
}
composerItem->setCustomProperty( "variableNames", variableNames );
composerItem->setCustomProperty( "variableValues", variableValues );
}
QgsExpressionContext QgsExpressionContextUtils::createFeatureBasedContext( const QgsFeature &feature, const QgsFields &fields )
{
QgsExpressionContextScope* scope = new QgsExpressionContextScope();

View File

@ -24,6 +24,9 @@
class QgsExpression;
class QgsMapLayer;
class QgsComposition;
class QgsComposerItem;
class QgsAtlasComposition;
/** \ingroup core
* \class QgsScopedExpressionFunction
@ -430,6 +433,62 @@ class CORE_EXPORT QgsExpressionContextUtils
*/
static void setLayerVariables( QgsMapLayer* layer, const QgsStringMap variables );
/** Creates a new scope which contains variables and functions relating to a QgsComposition.
* For instance, number of pages and page sizes.
* @param composition source composition
*/
static QgsExpressionContextScope* compositionScope( const QgsComposition *composition );
/** Sets a composition context variable. This variable will be contained within scopes retrieved via
* compositionScope().
* @param composition target composition
* @param name variable name
* @param value variable value
* @see setCompositionVariables()
* @see compositionScope()
*/
static void setCompositionVariable( QgsComposition* composition, const QString& name, const QVariant& value );
/** Sets all composition context variables. Existing composition variables will be removed and replaced
* with the variables specified.
* @param composition target composition
* @param variables new set of layer variables
* @see setCompositionVariable()
* @see compositionScope()
*/
static void setCompositionVariables( QgsComposition* composition, const QgsStringMap variables );
/** Creates a new scope which contains variables and functions relating to a QgsAtlasComposition.
* For instance, current page name and number.
* @param atlas source atlas
*/
static QgsExpressionContextScope* atlasScope( const QgsAtlasComposition* atlas );
/** Creates a new scope which contains variables and functions relating to a QgsComposerItem.
* For instance, item size and position.
* @param composerItem source composer item
*/
static QgsExpressionContextScope* composerItemScope( const QgsComposerItem *composerItem );
/** Sets a composer item context variable. This variable will be contained within scopes retrieved via
* composerItemScope().
* @param composerItem target composer item
* @param name variable name
* @param value variable value
* @see setComposerItemVariables()
* @see composerItemScope()
*/
static void setComposerItemVariable( QgsComposerItem* composerItem, const QString& name, const QVariant& value );
/** Sets all composition context variables. Existing compositoin variables will be removed and replaced
* with the variables specified.
* @param composerItem target composer item
* @param variables new set of layer variables
* @see setComposerItemVariable()
* @see composerItemScope()
*/
static void setComposerItemVariables( QgsComposerItem* composerItem, const QgsStringMap variables );
/** Helper function for creating an expression context which contains just a feature and fields
* collection. Generally this method should not be used as the created context does not include
* standard scopes such as the global and project scopes.

View File

@ -703,6 +703,25 @@
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="groupBox_3">
<property name="title">
<string>Variables</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QgsVariableEditorWidget" name="mVariableEditor" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@ -759,6 +778,18 @@
<extends>QComboBox</extends>
<header>qgsblendmodecombobox.h</header>
</customwidget>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsVariableEditorWidget</class>
<extends>QWidget</extends>
<header location="global">qgsvariableeditorwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>mGeneralOptionsGroupBox</tabstop>

View File

@ -23,7 +23,16 @@
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -50,9 +59,9 @@
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<y>-337</y>
<width>327</width>
<height>586</height>
<height>841</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
@ -137,7 +146,7 @@
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="showClearButton">
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
</widget>
@ -180,7 +189,7 @@
<property name="maximum">
<double>99999.000000000000000</double>
</property>
<property name="showClearButton">
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
</widget>
@ -234,7 +243,7 @@
<property name="minimum">
<number>1</number>
</property>
<property name="showClearButton">
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
</widget>
@ -317,7 +326,7 @@
<property name="maximum">
<number>3000</number>
</property>
<property name="showClearButton">
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
</widget>
@ -406,7 +415,7 @@
<property name="maximum">
<double>9999.000000000000000</double>
</property>
<property name="showClearButton">
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
</widget>
@ -466,7 +475,7 @@
<property name="maximum">
<number>200</number>
</property>
<property name="showClearButton">
<property name="showClearButton" stdset="0">
<bool>false</bool>
</property>
</widget>
@ -474,6 +483,25 @@
</layout>
</widget>
</item>
<item>
<widget class="QgsCollapsibleGroupBox" name="groupBox_2">
<property name="title">
<string>Variables</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QgsVariableEditorWidget" name="mVariableEditor" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>200</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
@ -495,6 +523,18 @@
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QgsCollapsibleGroupBox</class>
<extends>QGroupBox</extends>
<header>qgscollapsiblegroupbox.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsVariableEditorWidget</class>
<extends>QWidget</extends>
<header location="global">qgsvariableeditorwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsDataDefinedButton</class>
<extends>QToolButton</extends>