Fix memory leaks in classification methods, use unique_ptrs

This commit is contained in:
Nyall Dawson 2024-12-18 11:20:23 +10:00
parent b4f6d2e907
commit 75c8e3e2c4
42 changed files with 78 additions and 78 deletions

View File

@ -24,7 +24,7 @@ which does not compute any break.
public:
QgsClassificationCustom();
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QString name() const;

View File

@ -27,7 +27,7 @@ for equal intervals
virtual QString id() const;
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QIcon icon() const;

View File

@ -23,7 +23,7 @@ Implementation of a fixed interval classification.
public:
QgsClassificationFixedInterval();
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QString name() const;

View File

@ -27,7 +27,7 @@ for natural breaks based on Jenks method
virtual QString id() const;
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QIcon icon() const;

View File

@ -30,7 +30,7 @@ Implementation of a logarithmic scale method
};
QgsClassificationLogarithmic();
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QString name() const;

View File

@ -123,7 +123,7 @@ Creates a classification method.
virtual ~QgsClassificationMethod();
virtual QgsClassificationMethod *clone() const = 0 /Factory/;
virtual std::unique_ptr< QgsClassificationMethod > clone() const = 0;
%Docstring
Returns a clone of the method.
Implementation can take advantage of copyBase method which copies the parameters of the base class
@ -296,7 +296,7 @@ Saves the method to a DOM element and return it
:param context: the read/write context
%End
static QgsClassificationMethod *create( const QDomElement &element, const QgsReadWriteContext &context ) /Factory/;
static std::unique_ptr< QgsClassificationMethod > create( const QDomElement &element, const QgsReadWriteContext &context );
%Docstring
Reads the DOM element and return a new classification method from it

View File

@ -36,7 +36,7 @@ Adds a method to the registry
Returns ``False`` if a method with same id already exists.
%End
QgsClassificationMethod *method( const QString &id ) /Factory/;
std::unique_ptr< QgsClassificationMethod > method( const QString &id );
%Docstring
Returns a new instance of the method for the given id
%End

View File

@ -27,7 +27,7 @@ for pretty breaks
virtual QString id() const;
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QIcon icon() const;

View File

@ -28,7 +28,7 @@ based on quantiles
virtual QString id() const;
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QIcon icon() const;

View File

@ -27,7 +27,7 @@ based on standard deviation
virtual QString id() const;
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QIcon icon() const;

View File

@ -24,7 +24,7 @@ which does not compute any break.
public:
QgsClassificationCustom();
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QString name() const;

View File

@ -27,7 +27,7 @@ for equal intervals
virtual QString id() const;
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QIcon icon() const;

View File

@ -23,7 +23,7 @@ Implementation of a fixed interval classification.
public:
QgsClassificationFixedInterval();
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QString name() const;

View File

@ -27,7 +27,7 @@ for natural breaks based on Jenks method
virtual QString id() const;
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QIcon icon() const;

View File

@ -30,7 +30,7 @@ Implementation of a logarithmic scale method
};
QgsClassificationLogarithmic();
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QString name() const;

View File

@ -123,7 +123,7 @@ Creates a classification method.
virtual ~QgsClassificationMethod();
virtual QgsClassificationMethod *clone() const = 0 /Factory/;
virtual std::unique_ptr< QgsClassificationMethod > clone() const = 0;
%Docstring
Returns a clone of the method.
Implementation can take advantage of copyBase method which copies the parameters of the base class
@ -296,7 +296,7 @@ Saves the method to a DOM element and return it
:param context: the read/write context
%End
static QgsClassificationMethod *create( const QDomElement &element, const QgsReadWriteContext &context ) /Factory/;
static std::unique_ptr< QgsClassificationMethod > create( const QDomElement &element, const QgsReadWriteContext &context );
%Docstring
Reads the DOM element and return a new classification method from it

View File

@ -36,7 +36,7 @@ Adds a method to the registry
Returns ``False`` if a method with same id already exists.
%End
QgsClassificationMethod *method( const QString &id ) /Factory/;
std::unique_ptr< QgsClassificationMethod > method( const QString &id );
%Docstring
Returns a new instance of the method for the given id
%End

View File

@ -27,7 +27,7 @@ for pretty breaks
virtual QString id() const;
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QIcon icon() const;

View File

@ -28,7 +28,7 @@ based on quantiles
virtual QString id() const;
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QIcon icon() const;

View File

@ -27,7 +27,7 @@ based on standard deviation
virtual QString id() const;
virtual QgsClassificationMethod *clone() const;
virtual std::unique_ptr< QgsClassificationMethod > clone() const;
virtual QIcon icon() const;

View File

@ -25,10 +25,10 @@ QgsClassificationCustom::QgsClassificationCustom()
}
QgsClassificationMethod *QgsClassificationCustom::clone() const
std::unique_ptr<QgsClassificationMethod> QgsClassificationCustom::clone() const
{
QgsClassificationCustom *c = new QgsClassificationCustom();
copyBase( c );
std::unique_ptr< QgsClassificationCustom > c = std::make_unique< QgsClassificationCustom >();
copyBase( c.get() );
return c;
}

View File

@ -30,7 +30,7 @@ class CORE_EXPORT QgsClassificationCustom : public QgsClassificationMethod
public:
QgsClassificationCustom();
QgsClassificationMethod *clone() const override;
std::unique_ptr< QgsClassificationMethod > clone() const override;
QString name() const override;
QString id() const override;

View File

@ -91,10 +91,10 @@ QList<double> QgsClassificationEqualInterval::calculateBreaks( double &minimum,
}
QgsClassificationMethod *QgsClassificationEqualInterval::clone() const
std::unique_ptr< QgsClassificationMethod > QgsClassificationEqualInterval::clone() const
{
QgsClassificationEqualInterval *c = new QgsClassificationEqualInterval();
copyBase( c );
std::unique_ptr< QgsClassificationEqualInterval > c = std::make_unique< QgsClassificationEqualInterval >();
copyBase( c.get() );
return c;
}

View File

@ -32,7 +32,7 @@ class CORE_EXPORT QgsClassificationEqualInterval : public QgsClassificationMetho
QString name() const override;
QString id() const override;
QgsClassificationMethod *clone() const override;
std::unique_ptr< QgsClassificationMethod > clone() const override;
QIcon icon() const override;
bool valuesRequired() const override { return false; }

View File

@ -27,10 +27,10 @@ QgsClassificationFixedInterval::QgsClassificationFixedInterval()
addParameter( param.release() );
}
QgsClassificationMethod *QgsClassificationFixedInterval::clone() const
std::unique_ptr<QgsClassificationMethod> QgsClassificationFixedInterval::clone() const
{
QgsClassificationFixedInterval *c = new QgsClassificationFixedInterval();
copyBase( c );
std::unique_ptr<QgsClassificationFixedInterval > c = std::make_unique< QgsClassificationFixedInterval >();
copyBase( c.get() );
return c;
}

View File

@ -30,7 +30,7 @@ class CORE_EXPORT QgsClassificationFixedInterval : public QgsClassificationMetho
public:
QgsClassificationFixedInterval();
QgsClassificationMethod *clone() const override;
std::unique_ptr< QgsClassificationMethod > clone() const override;
QString name() const override;
QString id() const override;
QIcon icon() const override;

View File

@ -35,10 +35,10 @@ QString QgsClassificationJenks::id() const
return QStringLiteral( "Jenks" );
}
QgsClassificationMethod *QgsClassificationJenks::clone() const
std::unique_ptr<QgsClassificationMethod> QgsClassificationJenks::clone() const
{
QgsClassificationJenks *c = new QgsClassificationJenks();
copyBase( c );
std::unique_ptr< QgsClassificationJenks > c = std::make_unique< QgsClassificationJenks >();
copyBase( c.get() );
return c;
}

View File

@ -32,7 +32,7 @@ class CORE_EXPORT QgsClassificationJenks : public QgsClassificationMethod
QString name() const override;
QString id() const override;
QgsClassificationMethod *clone() const override;
std::unique_ptr< QgsClassificationMethod > clone() const override;
QIcon icon() const override;
private:

View File

@ -29,10 +29,10 @@ QgsClassificationLogarithmic::QgsClassificationLogarithmic()
}
QgsClassificationMethod *QgsClassificationLogarithmic::clone() const
std::unique_ptr<QgsClassificationMethod> QgsClassificationLogarithmic::clone() const
{
QgsClassificationLogarithmic *c = new QgsClassificationLogarithmic();
copyBase( c );
std::unique_ptr<QgsClassificationLogarithmic > c = std::make_unique< QgsClassificationLogarithmic >();
copyBase( c.get() );
return c;
}

View File

@ -41,7 +41,7 @@ class CORE_EXPORT QgsClassificationLogarithmic : public QgsClassificationMethod
};
QgsClassificationLogarithmic();
QgsClassificationMethod *clone() const override;
std::unique_ptr< QgsClassificationMethod > clone() const override;
QString name() const override;
QString id() const override;
QIcon icon() const override;

View File

@ -59,10 +59,10 @@ void QgsClassificationMethod::copyBase( QgsClassificationMethod *c ) const
c->setParameterValues( mParameterValues );
}
QgsClassificationMethod *QgsClassificationMethod::create( const QDomElement &element, const QgsReadWriteContext &context )
std::unique_ptr< QgsClassificationMethod > QgsClassificationMethod::create( const QDomElement &element, const QgsReadWriteContext &context )
{
const QString methodId = element.attribute( QStringLiteral( "id" ) );
QgsClassificationMethod *method = QgsApplication::classificationMethodRegistry()->method( methodId );
std::unique_ptr< QgsClassificationMethod > method = QgsApplication::classificationMethodRegistry()->method( methodId );
// symmetric
QDomElement symmetricModeElem = element.firstChildElement( QStringLiteral( "symmetricMode" ) );

View File

@ -141,7 +141,7 @@ class CORE_EXPORT QgsClassificationMethod SIP_ABSTRACT
* Returns a clone of the method.
* Implementation can take advantage of copyBase method which copies the parameters of the base class
*/
virtual QgsClassificationMethod *clone() const = 0 SIP_FACTORY;
virtual std::unique_ptr< QgsClassificationMethod > clone() const = 0;
//! The readable and translate name of the method
virtual QString name() const = 0;
@ -282,7 +282,7 @@ class CORE_EXPORT QgsClassificationMethod SIP_ABSTRACT
* \param element the DOM element
* \param context the read/write context
*/
static QgsClassificationMethod *create( const QDomElement &element, const QgsReadWriteContext &context ) SIP_FACTORY;
static std::unique_ptr< QgsClassificationMethod > create( const QDomElement &element, const QgsReadWriteContext &context );
/**
* Remove the breaks that are above the existing opposite sign classes to keep colors symmetrically balanced around symmetryPoint

View File

@ -52,11 +52,11 @@ bool QgsClassificationMethodRegistry::addMethod( QgsClassificationMethod *method
return true;
}
QgsClassificationMethod *QgsClassificationMethodRegistry::method( const QString &id )
std::unique_ptr< QgsClassificationMethod > QgsClassificationMethodRegistry::method( const QString &id )
{
auto it = mMethods.constFind( id );
if ( it == mMethods.constEnd() )
return new QgsClassificationCustom();
return std::make_unique< QgsClassificationCustom >();
return it.value()->clone();
}

View File

@ -48,7 +48,7 @@ class CORE_EXPORT QgsClassificationMethodRegistry
bool addMethod( QgsClassificationMethod *method SIP_TRANSFER );
//! Returns a new instance of the method for the given id
QgsClassificationMethod *method( const QString &id ) SIP_FACTORY;
std::unique_ptr< QgsClassificationMethod > method( const QString &id );
//! Returns a map <name, id> of all registered methods.
QMap<QString, QString> methodNames() const;

View File

@ -48,10 +48,10 @@ QList<double> QgsClassificationPrettyBreaks::calculateBreaks( double &minimum, d
return breaks;
}
QgsClassificationMethod *QgsClassificationPrettyBreaks::clone() const
std::unique_ptr<QgsClassificationMethod> QgsClassificationPrettyBreaks::clone() const
{
QgsClassificationPrettyBreaks *c = new QgsClassificationPrettyBreaks();
copyBase( c );
std::unique_ptr< QgsClassificationPrettyBreaks > c = std::make_unique< QgsClassificationPrettyBreaks >();
copyBase( c.get() );
return c;
}

View File

@ -32,7 +32,7 @@ class CORE_EXPORT QgsClassificationPrettyBreaks : public QgsClassificationMethod
QString name() const override;
QString id() const override;
QgsClassificationMethod *clone() const override;
std::unique_ptr< QgsClassificationMethod > clone() const override;
QIcon icon() const override;
bool valuesRequired() const override {return false;}

View File

@ -32,10 +32,10 @@ QString QgsClassificationQuantile::id() const
return QStringLiteral( "Quantile" );
}
QgsClassificationMethod *QgsClassificationQuantile::clone() const
std::unique_ptr<QgsClassificationMethod> QgsClassificationQuantile::clone() const
{
QgsClassificationQuantile *c = new QgsClassificationQuantile();
copyBase( c );
std::unique_ptr<QgsClassificationQuantile > c = std::make_unique< QgsClassificationQuantile >();
copyBase( c.get() );
return c;
}

View File

@ -33,7 +33,7 @@ class CORE_EXPORT QgsClassificationQuantile : public QgsClassificationMethod
QString name() const override;
QString id() const override;
QgsClassificationMethod *clone() const override;
std::unique_ptr< QgsClassificationMethod > clone() const override;
QIcon icon() const override;
private:

View File

@ -38,10 +38,10 @@ QString QgsClassificationStandardDeviation::id() const
return METHOD_ID;
}
QgsClassificationMethod *QgsClassificationStandardDeviation::clone() const
std::unique_ptr< QgsClassificationMethod > QgsClassificationStandardDeviation::clone() const
{
QgsClassificationStandardDeviation *c = new QgsClassificationStandardDeviation();
copyBase( c );
std::unique_ptr<QgsClassificationStandardDeviation > c = std::make_unique< QgsClassificationStandardDeviation >();
copyBase( c.get() );
c->mStdDev = mStdDev;
return c;
}

View File

@ -32,7 +32,7 @@ class CORE_EXPORT QgsClassificationStandardDeviation : public QgsClassificationM
QString name() const override;
QString id() const override;
QgsClassificationMethod *clone() const override;
std::unique_ptr< QgsClassificationMethod > clone() const override;
QIcon icon() const override;
QString labelForRange( double lowerValue, double upperValue, ClassPosition position ) const override;
void writeXml( QDomElement &element, const QgsReadWriteContext &context ) const override;

View File

@ -321,7 +321,7 @@ QgsGraduatedSymbolRenderer *QgsGraduatedSymbolRenderer::clone() const
{
QgsGraduatedSymbolRenderer *r = new QgsGraduatedSymbolRenderer( mAttrName, mRanges );
r->setClassificationMethod( mClassificationMethod->clone() );
r->setClassificationMethod( mClassificationMethod->clone().release() );
if ( mSourceSymbol )
r->setSourceSymbol( mSourceSymbol->clone() );
@ -412,12 +412,12 @@ QgsGraduatedSymbolRenderer *QgsGraduatedSymbolRenderer::createRenderer(
Q_UNUSED( listForCboPrettyBreaks )
QgsRangeList ranges;
QgsGraduatedSymbolRenderer *r = new QgsGraduatedSymbolRenderer( attrName, ranges );
std::unique_ptr< QgsGraduatedSymbolRenderer > r = std::make_unique< QgsGraduatedSymbolRenderer >( attrName, ranges );
r->setSourceSymbol( symbol->clone() );
r->setSourceColorRamp( ramp->clone() );
QString methodId = methodIdFromMode( mode );
QgsClassificationMethod *method = QgsApplication::classificationMethodRegistry()->method( methodId );
std::unique_ptr< QgsClassificationMethod > method = QgsApplication::classificationMethodRegistry()->method( methodId );
if ( method )
{
@ -426,13 +426,13 @@ QgsGraduatedSymbolRenderer *QgsGraduatedSymbolRenderer::createRenderer(
method->setLabelTrimTrailingZeroes( labelFormat.trimTrailingZeroes() );
method->setLabelPrecision( labelFormat.precision() );
}
r->setClassificationMethod( method );
r->setClassificationMethod( method.release() );
QString error;
r->updateClasses( vlayer, classes, error );
( void )error;
return r;
return r.release();
}
Q_NOWARN_DEPRECATED_POP
@ -443,9 +443,9 @@ void QgsGraduatedSymbolRenderer::updateClasses( QgsVectorLayer *vlayer, Mode mod
return;
QString methodId = methodIdFromMode( mode );
QgsClassificationMethod *method = QgsApplication::classificationMethodRegistry()->method( methodId );
std::unique_ptr< QgsClassificationMethod > method = QgsApplication::classificationMethodRegistry()->method( methodId );
method->setSymmetricMode( useSymmetricMode, symmetryPoint, astride );
setClassificationMethod( method );
setClassificationMethod( method.release() );
QString error;
updateClasses( vlayer, nclasses, error );
@ -513,7 +513,7 @@ QgsFeatureRenderer *QgsGraduatedSymbolRenderer::create( QDomElement &element, co
QString attrName = element.attribute( QStringLiteral( "attr" ) );
QgsGraduatedSymbolRenderer *r = new QgsGraduatedSymbolRenderer( attrName, ranges );
std::unique_ptr< QgsGraduatedSymbolRenderer > r = std::make_unique< QgsGraduatedSymbolRenderer >( attrName, ranges );
QString attrMethod = element.attribute( QStringLiteral( "graduatedMethod" ) );
if ( !attrMethod.isEmpty() )
@ -551,7 +551,7 @@ QgsFeatureRenderer *QgsGraduatedSymbolRenderer::create( QDomElement &element, co
QDomElement modeElem = element.firstChildElement( QStringLiteral( "mode" ) ); // old format, backward compatibility
QDomElement methodElem = element.firstChildElement( QStringLiteral( "classificationMethod" ) );
QgsClassificationMethod *method = nullptr;
std::unique_ptr< QgsClassificationMethod > method;
// TODO QGIS 4 Remove
// backward compatibility for QGIS project < 3.10
@ -603,7 +603,7 @@ QgsFeatureRenderer *QgsGraduatedSymbolRenderer::create( QDomElement &element, co
}
// apply the method
r->setClassificationMethod( method );
r->setClassificationMethod( method.release() );
QDomElement rotationElem = element.firstChildElement( QStringLiteral( "rotation" ) );
if ( !rotationElem.isNull() && !rotationElem.attribute( QStringLiteral( "field" ) ).isEmpty() )
@ -640,7 +640,7 @@ QgsFeatureRenderer *QgsGraduatedSymbolRenderer::create( QDomElement &element, co
r->mDataDefinedSizeLegend.reset( QgsDataDefinedSizeLegend::readXml( ddsLegendSizeElem, context ) );
}
// TODO: symbol levels
return r;
return r.release();
}
QDomElement QgsGraduatedSymbolRenderer::save( QDomDocument &doc, const QgsReadWriteContext &context )
@ -1273,8 +1273,8 @@ void QgsGraduatedSymbolRenderer::setClassificationMethod( QgsClassificationMetho
void QgsGraduatedSymbolRenderer::setMode( QgsGraduatedSymbolRenderer::Mode mode )
{
QString methodId = methodIdFromMode( mode );
QgsClassificationMethod *method = QgsApplication::classificationMethodRegistry()->method( methodId );
setClassificationMethod( method );
std::unique_ptr< QgsClassificationMethod > method = QgsApplication::classificationMethodRegistry()->method( methodId );
setClassificationMethod( method.release() );
}
void QgsGraduatedSymbolRenderer::setUseSymmetricMode( bool useSymmetricMode ) SIP_DEPRECATED

View File

@ -872,7 +872,7 @@ void QgsGraduatedSymbolRendererWidget::updateMethodParameters()
clearParameterWidgets();
const QString methodId = cboGraduatedMode->currentData().toString();
QgsClassificationMethod *method = QgsApplication::classificationMethodRegistry()->method( methodId );
std::unique_ptr< QgsClassificationMethod > method = QgsApplication::classificationMethodRegistry()->method( methodId );
Q_ASSERT( method );
// need more context?
@ -1044,7 +1044,7 @@ void QgsGraduatedSymbolRendererWidget::classifyGraduatedImpl()
int nclasses = spinGraduatedClasses->value();
const QString methodId = cboGraduatedMode->currentData().toString();
QgsClassificationMethod *method = QgsApplication::classificationMethodRegistry()->method( methodId );
std::unique_ptr< QgsClassificationMethod > method = QgsApplication::classificationMethodRegistry()->method( methodId );
Q_ASSERT( method );
int attrNum = mLayer->fields().lookupField( attrName );
@ -1081,14 +1081,14 @@ void QgsGraduatedSymbolRendererWidget::classifyGraduatedImpl()
method->setParameterValues( parameterValues );
// set method to renderer
mRenderer->setClassificationMethod( method );
mRenderer->setClassificationMethod( method.release() );
// create and set new renderer
mRenderer->setClassAttribute( attrName );
// If complexity >= oN^2, warn for big dataset (more than 50k records)
// and give the user the chance to cancel
if ( method->codeComplexity() > 1 && mLayer->featureCount() > 50000 )
if ( mRenderer->classificationMethod()->codeComplexity() > 1 && mLayer->featureCount() > 50000 )
{
if ( QMessageBox::Cancel == QMessageBox::question( this, tr( "Apply Classification" ), tr( "Natural break classification (Jenks) is O(n2) complexity, your classification may take a long time.\nPress cancel to abort breaks calculation or OK to continue." ), QMessageBox::Cancel, QMessageBox::Ok ) )
{