Skip to content

Commit 9094575

Browse files
committed
Merge branch 'master' of https://github.com/qgis/QGIS
Conflicts: src/gui/attributetable/qgsfieldconditionalformatwidget.cpp
2 parents 01d635a + 385a608 commit 9094575

34 files changed

+182
-66
lines changed

python/core/qgsexpression.sip

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,9 +299,24 @@ class QgsExpression
299299
static const QList<QgsExpression::Function *>& Functions();
300300
static const QStringList& BuiltinFunctions();
301301

302+
/** Registers a function to the expression engine. This is required to allow expressions to utilise the function.
303+
* @param function function to register
304+
* @returns true on successful registration
305+
* @see unregisterFunction
306+
*/
302307
static bool registerFunction( Function* function );
308+
309+
/** Unregisters a function from the expression engine. The function will no longer be usable in expressions.
310+
* @param name function name
311+
* @see registerFunction
312+
*/
303313
static bool unregisterFunction( QString name );
304314

315+
/** Deletes all registered functions whose ownership have been transferred to the expression engine.
316+
* @note added in QGIS 2.12
317+
*/
318+
static void cleanRegisteredFunctions();
319+
305320
// tells whether the identifier is a name of existing function
306321
static bool isFunctionName( const QString& name );
307322

src/core/composer/qgscomposerobject.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ QgsComposerObject::QgsComposerObject( QgsComposition* composition )
5555

5656
QgsComposerObject::~QgsComposerObject()
5757
{
58-
58+
qDeleteAll( mDataDefinedProperties );
5959
}
6060

6161
bool QgsComposerObject::writeXML( QDomElement &elem, QDomDocument &doc ) const

src/core/geometry/qgsgeometry.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,13 @@ const QgsAbstractGeometryV2* QgsGeometry::geometry() const
146146
void QgsGeometry::setGeometry( QgsAbstractGeometryV2* geometry )
147147
{
148148
detach( false );
149+
if ( d->geometry )
150+
{
151+
delete d->geometry;
152+
d->geometry = 0;
153+
}
154+
removeWkbGeos();
155+
149156
d->geometry = geometry;
150157
}
151158

src/core/qgsapplication.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "qgsmaplayerregistry.h"
2323
#include "qgsnetworkaccessmanager.h"
2424
#include "qgsproviderregistry.h"
25+
#include "qgsexpression.h"
2526

2627
#include <QDir>
2728
#include <QFile>
@@ -629,6 +630,14 @@ void QgsApplication::initQgis()
629630
void QgsApplication::exitQgis()
630631
{
631632
delete QgsProviderRegistry::instance();
633+
634+
//Ensure that all remaining deleteLater QObjects are actually deleted before we exit.
635+
//This isn't strictly necessary (since we're exiting anyway) but doing so prevents a lot of
636+
//LeakSanitiser noise which hides real issues
637+
QgsApplication::sendPostedEvents( 0, QEvent::DeferredDelete );
638+
639+
//delete all registered functions from expression engine (see above comment)
640+
QgsExpression::cleanRegisteredFunctions();
632641
}
633642

634643
QString QgsApplication::showSettings()

src/core/qgsdistancearea.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ QgsDistanceArea::QgsDistanceArea()
5656

5757
//! Copy constructor
5858
QgsDistanceArea::QgsDistanceArea( const QgsDistanceArea & origDA )
59+
: mCoordTransform( 0 )
5960
{
6061
_copy( origDA );
6162
}
@@ -88,6 +89,7 @@ void QgsDistanceArea::_copy( const QgsDistanceArea & origDA )
8889
// Some calculations and trig. Should not be TOO time consuming.
8990
// Alternatively we could copy the temp vars?
9091
computeAreaInit();
92+
delete mCoordTransform;
9193
mCoordTransform = new QgsCoordinateTransform( origDA.mCoordTransform->sourceCrs(), origDA.mCoordTransform->destCRS() );
9294
}
9395

src/core/qgsexpression.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,14 +1767,16 @@ static QVariant fcnGetLayerProperty( const QVariantList& values, const QgsExpres
17671767
return QVariant();
17681768
}
17691769

1770-
bool QgsExpression::registerFunction( QgsExpression::Function* function )
1770+
bool QgsExpression::registerFunction( QgsExpression::Function* function, bool transferOwnership )
17711771
{
17721772
int fnIdx = functionIndex( function->name() );
17731773
if ( fnIdx != -1 )
17741774
{
17751775
return false;
17761776
}
17771777
QgsExpression::gmFunctions.append( function );
1778+
if ( transferOwnership )
1779+
QgsExpression::gmOwnedFunctions.append( function );
17781780
return true;
17791781
}
17801782

@@ -1794,7 +1796,11 @@ bool QgsExpression::unregisterFunction( QString name )
17941796
return false;
17951797
}
17961798

1797-
1799+
void QgsExpression::cleanRegisteredFunctions()
1800+
{
1801+
qDeleteAll( QgsExpression::gmOwnedFunctions );
1802+
QgsExpression::gmOwnedFunctions.clear();
1803+
}
17981804

17991805
QStringList QgsExpression::gmBuiltinFunctions;
18001806

@@ -1842,6 +1848,7 @@ const QStringList& QgsExpression::BuiltinFunctions()
18421848
}
18431849

18441850
QList<QgsExpression::Function*> QgsExpression::gmFunctions;
1851+
QList<QgsExpression::Function*> QgsExpression::gmOwnedFunctions;
18451852

18461853
const QList<QgsExpression::Function*>& QgsExpression::Functions()
18471854
{
@@ -1978,6 +1985,12 @@ const QList<QgsExpression::Function*>& QgsExpression::Functions()
19781985
;
19791986

19801987
QgsExpressionContextUtils::registerContextFunctions();
1988+
1989+
//QgsExpression has ownership of all built-in functions
1990+
Q_FOREACH ( QgsExpression::Function* func, gmFunctions )
1991+
{
1992+
gmOwnedFunctions << func;
1993+
}
19811994
}
19821995
return gmFunctions;
19831996
}

src/core/qgsexpression.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,9 +490,28 @@ class CORE_EXPORT QgsExpression
490490
static QStringList gmBuiltinFunctions;
491491
static const QStringList& BuiltinFunctions();
492492

493-
static bool registerFunction( Function* function );
493+
/** Registers a function to the expression engine. This is required to allow expressions to utilise the function.
494+
* @param function function to register
495+
* @param transferOwnership set to true to transfer ownership of function to expression engine
496+
* @returns true on successful registration
497+
* @see unregisterFunction
498+
*/
499+
static bool registerFunction( Function* function, bool transferOwnership = false );
500+
501+
/** Unregisters a function from the expression engine. The function will no longer be usable in expressions.
502+
* @param name function name
503+
* @see registerFunction
504+
*/
494505
static bool unregisterFunction( QString name );
495506

507+
//! List of functions owned by the expression engine
508+
static QList<Function*> gmOwnedFunctions;
509+
510+
/** Deletes all registered functions whose ownership have been transferred to the expression engine.
511+
* @note added in QGIS 2.12
512+
*/
513+
static void cleanRegisteredFunctions();
514+
496515
// tells whether the identifier is a name of existing function
497516
static bool isFunctionName( const QString& name );
498517

src/core/qgsexpressionlexer.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ struct expression_parser_context;
5050

5151
#define B_OP(x) yylval->b_op = QgsExpression::x
5252
#define U_OP(x) yylval->u_op = QgsExpression::x
53-
#define TEXT yylval->text = new QString(); *yylval->text = QString::fromUtf8(yytext);
54-
#define TEXT_FILTER(filter_fn) yylval->text = new QString(); *yylval->text = filter_fn( QString::fromUtf8(yytext) );
53+
#define TEXT yylval->text = new QString( QString::fromUtf8(yytext) );
54+
#define TEXT_FILTER(filter_fn) yylval->text = new QString( filter_fn( QString::fromUtf8(yytext) ) );
5555

5656
static QString stripText(QString text)
5757
{

src/core/qgsexpressionparser.yy

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ struct expression_parser_context
149149
%destructor { delete $$; } <node>
150150
%destructor { delete $$; } <nodelist>
151151
%destructor { delete $$; } <text>
152+
%destructor { delete $$; } <whenthen>
153+
%destructor { delete $$; } <whenthenlist>
152154

153155
%%
154156

@@ -181,26 +183,29 @@ expression:
181183
| FUNCTION '(' exp_list ')'
182184
{
183185
int fnIndex = QgsExpression::functionIndex(*$1);
186+
delete $1;
184187
if (fnIndex == -1)
185188
{
186189
// this should not actually happen because already in lexer we check whether an identifier is a known function
187190
// (if the name is not known the token is parsed as a column)
188191
exp_error(parser_ctx, "Function is not known");
192+
delete $3;
189193
YYERROR;
190194
}
191195
if ( QgsExpression::Functions()[fnIndex]->params() != -1
192196
&& QgsExpression::Functions()[fnIndex]->params() != $3->count() )
193197
{
194198
exp_error(parser_ctx, "Function is called with wrong number of arguments");
199+
delete $3;
195200
YYERROR;
196201
}
197202
$$ = new QgsExpression::NodeFunction(fnIndex, $3);
198-
delete $1;
199203
}
200204

201205
| FUNCTION '(' ')'
202206
{
203207
int fnIndex = QgsExpression::functionIndex(*$1);
208+
delete $1;
204209
if (fnIndex == -1)
205210
{
206211
// this should not actually happen because already in lexer we check whether an identifier is a known function
@@ -214,7 +219,6 @@ expression:
214219
YYERROR;
215220
}
216221
$$ = new QgsExpression::NodeFunction(fnIndex, new QgsExpression::NodeList());
217-
delete $1;
218222
}
219223

220224
| expression IN '(' exp_list ')' { $$ = new QgsExpression::NodeInOperator($1, $4, false); }
@@ -236,30 +240,31 @@ expression:
236240
if (fnIndex == -1)
237241
{
238242
if ( !QgsExpression::hasSpecialColumn( *$1 ) )
239-
{
243+
{
240244
exp_error(parser_ctx, "Special column is not known");
241-
YYERROR;
242-
}
243-
// $var is equivalent to _specialcol_( "$var" )
244-
QgsExpression::NodeList* args = new QgsExpression::NodeList();
245-
QgsExpression::NodeLiteral* literal = new QgsExpression::NodeLiteral( *$1 );
246-
args->append( literal );
247-
$$ = new QgsExpression::NodeFunction( QgsExpression::functionIndex( "_specialcol_" ), args );
245+
delete $1;
246+
YYERROR;
247+
}
248+
// $var is equivalent to _specialcol_( "$var" )
249+
QgsExpression::NodeList* args = new QgsExpression::NodeList();
250+
QgsExpression::NodeLiteral* literal = new QgsExpression::NodeLiteral( *$1 );
251+
args->append( literal );
252+
$$ = new QgsExpression::NodeFunction( QgsExpression::functionIndex( "_specialcol_" ), args );
248253
}
249-
else
250-
{
251-
$$ = new QgsExpression::NodeFunction( fnIndex, NULL );
252-
delete $1;
253-
}
254+
else
255+
{
256+
$$ = new QgsExpression::NodeFunction( fnIndex, NULL );
257+
}
258+
delete $1;
254259
}
255260

256261
// variables
257262
| VARIABLE
258263
{
259-
// @var is equivalent to var( "var" )
260-
QgsExpression::NodeList* args = new QgsExpression::NodeList();
261-
QgsExpression::NodeLiteral* literal = new QgsExpression::NodeLiteral( QString(*$1).mid(1) );
262-
args->append( literal );
264+
// @var is equivalent to var( "var" )
265+
QgsExpression::NodeList* args = new QgsExpression::NodeList();
266+
QgsExpression::NodeLiteral* literal = new QgsExpression::NodeLiteral( QString(*$1).mid(1) );
267+
args->append( literal );
263268
$$ = new QgsExpression::NodeFunction( QgsExpression::functionIndex( "var" ), args );
264269
delete $1;
265270
}
@@ -308,6 +313,7 @@ QgsExpression::Node* parseExpression(const QString& str, QString& parserErrorMsg
308313
else // error?
309314
{
310315
parserErrorMsg = ctx.errorMsg;
316+
delete ctx.rootNode;
311317
return NULL;
312318
}
313319
}

src/core/qgsvectorlayer.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ QgsVectorLayer::~QgsVectorLayer()
186186
delete mCache;
187187
delete mLabel;
188188
delete mDiagramLayerSettings;
189+
delete mDiagramRenderer;
189190

190191
delete mActions;
191192

@@ -2244,7 +2245,7 @@ bool QgsVectorLayer::deleteAttributes( QList<int> attrs )
22442245

22452246
qSort( attrs.begin(), attrs.end(), qGreater<int>() );
22462247

2247-
Q_FOREACH( int attr, attrs )
2248+
Q_FOREACH ( int attr, attrs )
22482249
{
22492250
if ( deleteAttribute( attr ) )
22502251
{
@@ -3003,7 +3004,7 @@ void QgsVectorLayer::uniqueValues( int index, QList<QVariant> &uniqueValues, int
30033004
if ( mEditBuffer )
30043005
{
30053006
QSet<QString> vals;
3006-
Q_FOREACH( const QVariant& v, uniqueValues )
3007+
Q_FOREACH ( const QVariant& v, uniqueValues )
30073008
{
30083009
vals << v.toString();
30093010
}
@@ -3833,7 +3834,7 @@ void QgsVectorLayer::invalidateSymbolCountedFlag()
38333834

38343835
void QgsVectorLayer::onRelationsLoaded()
38353836
{
3836-
Q_FOREACH( QgsAttributeEditorElement* elem, mAttributeEditorElements )
3837+
Q_FOREACH ( QgsAttributeEditorElement* elem, mAttributeEditorElements )
38373838
{
38383839
if ( elem->type() == QgsAttributeEditorElement::AeTypeContainer )
38393840
{
@@ -3842,7 +3843,7 @@ void QgsVectorLayer::onRelationsLoaded()
38423843
continue;
38433844

38443845
QList<QgsAttributeEditorElement*> relations = cont->findElements( QgsAttributeEditorElement::AeTypeRelation );
3845-
Q_FOREACH( QgsAttributeEditorElement* relElem, relations )
3846+
Q_FOREACH ( QgsAttributeEditorElement* relElem, relations )
38463847
{
38473848
QgsAttributeEditorRelation* rel = dynamic_cast< QgsAttributeEditorRelation* >( relElem );
38483849
if ( !rel )
@@ -3911,7 +3912,7 @@ QDomElement QgsAttributeEditorContainer::toDomElement( QDomDocument& doc ) const
39113912
QDomElement elem = doc.createElement( "attributeEditorContainer" );
39123913
elem.setAttribute( "name", mName );
39133914

3914-
Q_FOREACH( QgsAttributeEditorElement* child, mChildren )
3915+
Q_FOREACH ( QgsAttributeEditorElement* child, mChildren )
39153916
{
39163917
elem.appendChild( child->toDomElement( doc ) );
39173918
}
@@ -3932,7 +3933,7 @@ QList<QgsAttributeEditorElement*> QgsAttributeEditorContainer::findElements( Qgs
39323933
{
39333934
QList<QgsAttributeEditorElement*> results;
39343935

3935-
Q_FOREACH( QgsAttributeEditorElement* elem, mChildren )
3936+
Q_FOREACH ( QgsAttributeEditorElement* elem, mChildren )
39363937
{
39373938
if ( elem->type() == type )
39383939
{

0 commit comments

Comments
 (0)