Skip to content

Commit adafeda

Browse files
committed
Avoid all use of QgsCoordinateTransform pointers, replace with
copies or references Makes the code more robust, fixes leaks and avoids potential null pointer dereferencing
1 parent ffa9b9b commit adafeda

File tree

64 files changed

+453
-421
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+453
-421
lines changed

doc/api_break.dox

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,30 @@ plugins calling these methods will need to be updated.</li>
3737
<li>readXML() and writeXML() have been renamed to readXml() and writeXml() for consistency</li>
3838
</ul>
3939

40+
\subsection qgis_api_break_3_0_QgsCoordinateTransformCache QgsCoordinateTransformCache
41+
42+
<ul>
43+
<li>transform() now returns a QgsCoordinateTransform object, not a pointer. An invalid QgsCoordinateTransform will
44+
be returned in place of a null pointer.</li>
45+
</ul>
46+
47+
\subsection qgis_api_break_3_0_QgsDiagramLayerSettings QgsDiagramLayerSettings
48+
49+
<ul>
50+
<li>coordinateTransform() now returns a QgsCoordinateTransform object, not a pointer. An invalid QgsCoordinateTransform will
51+
be returned in place of a null pointer.</li>
52+
<li>setCoordinateTransform() now takes a QgsCoordinateTransform object, not a pointer. Use an invalid QgsCoordinateTransform in
53+
place of a null pointer.</li>
54+
<li>The ct member has been removed. Use coordinateTransform() and setCoordinateTransform() instead.
55+
</ul>
56+
57+
\subsection qgis_api_break_3_0_QgsDatumTransformStore QgsDatumTransformStore
58+
59+
<ul>
60+
<li>transformation() now returns a QgsCoordinateTransform object, not a pointer. An invalid QgsCoordinateTransform will
61+
be returned in place of a null pointer.</li>
62+
</ul>
63+
4064
\subsection qgis_api_break_3_0_DataProviders Data Providers
4165

4266
<ul>
@@ -79,6 +103,43 @@ screenUpdateRequested() were removed. These members have had no effect for a num
79103
<li>theError parameter in appendError() and setError() were renamed to 'error'.</li>
80104
</ul>
81105

106+
\subsection qgis_api_break_3_0_QgsMapRenderer QgsMapRenderer
107+
108+
<ul>
109+
<li>transformation() now returns a QgsCoordinateTransform object, not a pointer. An invalid QgsCoordinateTransform will
110+
be returned instead of a null pointer if no transformation is required.</li>
111+
</ul>
112+
113+
\subsection qgis_api_break_3_0_QgsMapRendererJob QgsMapRendererJob
114+
115+
<ul>
116+
<li>reprojectToLayerExtent() now takes a QgsCoordinateTransform reference, not a pointer. An invalid QgsCoordinateTransform should
117+
be used instead of a null pointer if no transformation is required.</li>
118+
</ul>
119+
120+
\subsection qgis_api_break_3_0_QgsMapSettings QgsMapSettings
121+
122+
<ul>
123+
<li>layerTransform() now returns a QgsCoordinateTransform object, not a pointer. An invalid QgsCoordinateTransform will
124+
be returned instead of a null pointer if no transformation is required.</li>
125+
</ul>
126+
127+
\subsection qgis_api_break_3_0_QgsRenderContext QgsRenderContext
128+
129+
<ul>
130+
<li>coordinateTransform() now returns a QgsCoordinateTransform object, not a pointer. An invalid QgsCoordinateTransform will
131+
be returned instead of a null pointer if no transformation is required.</li>
132+
<li>setCoordinateTransform() now takes a QgsCoordinateTransform reference, not a pointer. An invalid QgsCoordinateTransform should be used instead of a null pointer if no transformation is required.</li>
133+
</ul>
134+
135+
\subsection qgis_api_break_3_0_QgsPalLayerSettings QgsPalLayerSettings
136+
137+
<ul>
138+
<li>ct is now a QgsCoordinateTransform object, not a pointer. An invalid QgsCoordinateTransform will
139+
be used instead of a null pointer if no transformation is required.</li>
140+
<li>prepareGeometry() and geometryRequiresPreparation() now take a QgsCoordinateTransform reference, not a pointer. An invalid QgsCoordinateTransform should be used instead of a null pointer if no transformation is required.</li>
141+
</ul>
142+
82143
\subsection qgis_api_break_3_0_QgsJSONExporter QgsJSONExporter
83144

84145
<ul>
@@ -125,13 +186,20 @@ plugins calling this method will need to be updated.</li>
125186
<li>subsetString() was made const. This has no effect on PyQGIS code, but c++ code implementing derived layer classes will need to update the signature of this method to match.</li>
126187
</ul>
127188

189+
\subsection qgis_api_break_3_0_QgsRasterProjector QgsRasterProjector
190+
191+
<ul>
192+
<li>extentSize() now takes a QgsCoordinateTransform reference, not a pointer. An invalid QgsCoordinateTransform should be used instead of a null pointer if no transformation is required.</li>
193+
</ul>
194+
128195
\subsection qgis_api_break_3_0_QgsVectorFileWriter QgsVectorFileWriter
129196

130197
<ul>
131198
<li>QgsVectorFileWriter now takes references instead of pointers to QgsCoordinateReferenceSystem objects. Since
132199
QgsCoordinateReferenceSystem is now implicitly shared, using references to QgsCoordinateReferenceSystem rather than
133200
pointers makes for more robust, safer code. Use an invalid (default constructed) QgsCoordinateReferenceSystem
134201
in code which previously passed a null pointer to QgsVectorFileWriter.</li>
202+
<li>writeAsVectorFormat() now takes a QgsCoordinateTransform reference, not a pointer. An invalid QgsCoordinateTransform should be used instead of a null pointer if no transformation is required.</li>
135203
</ul>
136204

137205
\subsection qgis_api_break_3_0_QgsVectorLayerEditBuffer QgsVectorLayerEditBuffer

python/core/qgscrscache.sip

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ class QgsCoordinateTransformCache
77
static QgsCoordinateTransformCache* instance();
88

99
~QgsCoordinateTransformCache();
10+
1011
/** Returns coordinate transformation. Cache keeps ownership
1112
@param srcAuthId auth id string of source crs
1213
@param destAuthId auth id string of dest crs
1314
@param srcDatumTransform id of source's datum transform
1415
@param destDatumTransform id of destinations's datum transform
16+
@returns matching transform, or an invalid transform if none could be created
1517
*/
16-
const QgsCoordinateTransform* transform( const QString& srcAuthId, const QString& destAuthId, int srcDatumTransform = -1, int destDatumTransform = -1 );
18+
QgsCoordinateTransform transform( const QString& srcAuthId, const QString& destAuthId, int srcDatumTransform = -1, int destDatumTransform = -1 );
19+
1720
/** Removes transformations where a changed crs is involved from the cache*/
1821
void invalidateCrs( const QString& crsAuthId );
1922

python/core/qgsdatumtransformstore.sip

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ class QgsDatumTransformStore
2323

2424
/** Will return transform from layer's CRS to current destination CRS.
2525
* Will emit datumTransformInfoRequested signal if the layer has no entry.
26-
* Returns an instance from QgsCoordinateTransformCache
26+
* @returns transformation associated with layer, or an invalid QgsCoordinateTransform
27+
* if no transform is associated with the layer
2728
*/
28-
const QgsCoordinateTransform* transformation( QgsMapLayer* layer ) const;
29+
QgsCoordinateTransform transformation( QgsMapLayer* layer ) const;
30+
2931

3032
void readXML( const QDomNode& parentNode );
3133

python/core/qgsdiagramrendererv2.sip

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -181,28 +181,19 @@ class QgsDiagramLayerSettings
181181
// TODO QGIS 3.0 - make private, rename to mRenderer
182182
QgsDiagramRendererV2* renderer;
183183

184-
/** Returns the coordinate transform associated with the layer.
184+
/** Returns the coordinate transform associated with the layer, or an
185+
* invalid transform if no transformation is required.
185186
* @see setCoordinateTransform()
186187
* @note added in QGIS 2.16
187188
*/
188-
QgsCoordinateTransform* coordinateTransform();
189-
190-
/** Returns the coordinate transform associated with the layer.
191-
* @see setCoordinateTransform()
192-
* @note added in QGIS 2.16
193-
*/
194-
//const QgsCoordinateTransform* coordinateTransform() const;
189+
QgsCoordinateTransform coordinateTransform() const;
195190

196191
/** Sets the coordinate transform associated with the layer.
197192
* @param transform coordinate transform. Ownership is transferred to the object.
198193
* @see coordinateTransform()
199194
* @note added in QGIS 2.16
200195
*/
201-
void setCoordinateTransform( QgsCoordinateTransform* transform /Transfer/ );
202-
203-
//! Associated coordinate transform. Owned by this object.
204-
// TODO QGIS 3.0 - make private, rename to mCt
205-
QgsCoordinateTransform* ct;
196+
void setCoordinateTransform( const QgsCoordinateTransform& transform );
206197

207198
//! @deprecated will be removed in QGIS 3.0
208199
const QgsMapToPixel* xform;

python/core/qgsmaprenderer.sip

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,10 @@ class QgsMapRenderer : QObject
305305
void addLayerCoordinateTransform( const QString& layerId, const QString& srcAuthId, const QString& destAuthId, int srcDatumTransform = -1, int destDatumTransform = -1 );
306306
void clearLayerCoordinateTransforms();
307307

308-
const QgsCoordinateTransform* transformation( const QgsMapLayer *layer ) const;
308+
/** Returns the coordinate transform associated with a renderered layer,
309+
* or an invalid transform is no transform is required for the layer.
310+
*/
311+
QgsCoordinateTransform transformation( const QgsMapLayer *layer ) const;
309312

310313
//! bridge to QgsMapSettings
311314
//! @note added in 2.4

python/core/qgsmaprendererjob.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ class QgsMapRendererJob : QObject
110110
* source CRS coordinates, and if it was split, returns true, and
111111
* also sets the contents of the r2 parameter
112112
*/
113-
static bool reprojectToLayerExtent( const QgsMapLayer *ml, const QgsCoordinateTransform *ct, QgsRectangle &extent, QgsRectangle &r2 );
113+
static bool reprojectToLayerExtent( const QgsMapLayer *ml, const QgsCoordinateTransform& ct, QgsRectangle &extent, QgsRectangle &r2 );
114114

115115
//! @note not available in python bindings
116116
// LayerRenderJobs prepareJobs( QPainter* painter, QgsPalLabeling* labelingEngine );

python/core/qgsmapsettings.sip

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,9 @@ class QgsMapSettings
218218
/**
219219
* @brief Return coordinate transform from layer's CRS to destination CRS
220220
* @param layer
221-
* @return transform - may be null if the transform is not needed
221+
* @return transform - may be invalid if the transform is not needed
222222
*/
223-
const QgsCoordinateTransform* layerTransform( QgsMapLayer *layer ) const;
223+
QgsCoordinateTransform layerTransform( QgsMapLayer *layer ) const;
224224

225225
//! returns current extent of layer set
226226
QgsRectangle fullExtent() const;

python/core/qgspallabeling.sip

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,7 @@ class QgsPalLayerSettings
662662
QgsFields mCurFields;
663663
int fieldIndex;
664664
const QgsMapToPixel* xform;
665-
const QgsCoordinateTransform* ct;
665+
QgsCoordinateTransform ct;
666666

667667
QgsPoint ptZero;
668668
QgsPoint ptOne;
@@ -916,22 +916,22 @@ class QgsPalLabeling : QgsLabelingEngineInterface
916916
/** Prepares a geometry for registration with PAL. Handles reprojection, rotation, clipping, etc.
917917
* @param geometry geometry to prepare
918918
* @param context render context
919-
* @param ct coordinate transform
919+
* @param ct coordinate transform, or invalid transform if no transformation required
920920
* @param clipGeometry geometry to clip features to, if applicable
921921
* @returns prepared geometry, the caller takes ownership
922922
* @note added in QGIS 2.9
923923
*/
924-
static QgsGeometry* prepareGeometry( const QgsGeometry *geometry, QgsRenderContext &context, const QgsCoordinateTransform *ct, QgsGeometry *clipGeometry = 0 ) /Factory/;
924+
static QgsGeometry* prepareGeometry( const QgsGeometry *geometry, QgsRenderContext &context, const QgsCoordinateTransform& ct, QgsGeometry *clipGeometry = 0 ) /Factory/;
925925

926926
/** Checks whether a geometry requires preparation before registration with PAL
927927
* @param geometry geometry to prepare
928928
* @param context render context
929-
* @param ct coordinate transform
929+
* @param @param ct coordinate transform, or invalid transform if no transformation required
930930
* @param clipGeometry geometry to clip features to, if applicable
931931
* @returns true if geometry requires preparation
932932
* @note added in QGIS 2.9
933933
*/
934-
static bool geometryRequiresPreparation( const QgsGeometry *geometry, QgsRenderContext &context, const QgsCoordinateTransform *ct, QgsGeometry *clipGeometry = 0 );
934+
static bool geometryRequiresPreparation( const QgsGeometry *geometry, QgsRenderContext &context, const QgsCoordinateTransform& ct, QgsGeometry *clipGeometry = 0 );
935935

936936
/** Splits a text string to a list of separate lines, using a specified wrap character.
937937
* The text string will be split on either newline characters or the wrap character.

python/core/qgsrendercontext.sip

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,10 @@ class QgsRenderContext
5555
QPainter* painter();
5656
const QPainter* constPainter() const;
5757

58-
const QgsCoordinateTransform* coordinateTransform() const;
58+
/** Returns the current coordinate transform for the context, or an invalid
59+
* transform is no coordinate transformation is required.
60+
*/
61+
QgsCoordinateTransform coordinateTransform() const;
5962

6063
const QgsRectangle& extent() const;
6164

@@ -99,8 +102,9 @@ class QgsRenderContext
99102

100103
//setters
101104

102-
/** Sets coordinate transformation. QgsRenderContext does not take ownership*/
103-
void setCoordinateTransform( const QgsCoordinateTransform* t );
105+
/** Sets coordinate transformation.*/
106+
void setCoordinateTransform( const QgsCoordinateTransform& t );
107+
104108
void setMapToPixel( const QgsMapToPixel& mtp );
105109
void setExtent( const QgsRectangle& extent );
106110

python/core/qgsvectorfilewriter.sip

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ class QgsVectorFileWriter
179179
* @param layer layer to write
180180
* @param fileName file name to write to
181181
* @param fileEncoding encoding to use
182-
* @param ct pointer to coordinate transform to reproject exported geometries with
182+
* @param ct coordinate transform to reproject exported geometries with, or invalid transform
183+
* for no transformation
183184
* @param driverName OGR driver to use
184185
* @param onlySelected write only selected features of layer
185186
* @param errorMessage pointer to buffer fo error message
@@ -201,7 +202,7 @@ class QgsVectorFileWriter
201202
static WriterError writeAsVectorFormat( QgsVectorLayer* layer,
202203
const QString& fileName,
203204
const QString& fileEncoding,
204-
const QgsCoordinateTransform* ct,
205+
const QgsCoordinateTransform& ct,
205206
const QString& driverName = "ESRI Shapefile",
206207
bool onlySelected = false,
207208
QString *errorMessage = 0,

python/core/raster/qgsrasterprojector.sip

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class QgsRasterProjector : QgsRasterInterface
8181
QgsRectangle& theDestExtent, int& theDestXSize, int& theDestYSize );
8282

8383
/** Calculate destination extent and size from source extent and size */
84-
static bool extentSize( const QgsCoordinateTransform* ct,
84+
static bool extentSize( const QgsCoordinateTransform& ct,
8585
const QgsRectangle& theSrcExtent, int theSrcXSize, int theSrcYSize,
8686
QgsRectangle& theDestExtent, int& theDestXSize, int& theDestYSize );
8787
};

src/app/nodetool/qgsmaptoolnodetool.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ void QgsMapToolNodeTool::createTopologyRubberBands()
9797
rb->setBrushStyle( Qt::NoBrush );
9898
rb->setOutlineWidth( settings.value( "/qgis/digitizing/line_width", 1 ).toInt() );
9999
QgsAbstractGeometryV2* rbGeom = feature.constGeometry()->geometry()->clone();
100-
if ( mCanvas->mapSettings().layerTransform( vlayer ) )
101-
rbGeom->transform( *mCanvas->mapSettings().layerTransform( vlayer ) );
100+
if ( mCanvas->mapSettings().layerTransform( vlayer ).isValid() )
101+
rbGeom->transform( mCanvas->mapSettings().layerTransform( vlayer ) );
102102
rb->setGeometry( rbGeom );
103103
mMoveRubberBands.insert( snapFeatureId, rb );
104104
}
@@ -140,8 +140,8 @@ void QgsMapToolNodeTool::canvasMoveEvent( QgsMapMouseEvent* e )
140140
rb->setBrushStyle( Qt::NoBrush );
141141
rb->setOutlineWidth( settings.value( "/qgis/digitizing/line_width", 1 ).toInt() );
142142
QgsAbstractGeometryV2* rbGeom = mSelectedFeature->geometry()->geometry()->clone();
143-
if ( mCanvas->mapSettings().layerTransform( vlayer ) )
144-
rbGeom->transform( *mCanvas->mapSettings().layerTransform( vlayer ) );
143+
if ( mCanvas->mapSettings().layerTransform( vlayer ).isValid() )
144+
rbGeom->transform( mCanvas->mapSettings().layerTransform( vlayer ) );
145145
rb->setGeometry( rbGeom );
146146
mMoveRubberBands.insert( mSelectedFeature->featureId(), rb );
147147
Q_FOREACH ( const QgsVertexEntry* vertexEntry, mSelectedFeature->vertexMap() )
@@ -402,8 +402,8 @@ void QgsMapToolNodeTool::updateSelectFeature( QgsGeometry &geom )
402402

403403
QgsAbstractGeometryV2* rbGeom = geom.geometry()->clone();
404404
QgsVectorLayer *vlayer = mSelectedFeature->vlayer();
405-
if ( mCanvas->mapSettings().layerTransform( vlayer ) )
406-
rbGeom->transform( *mCanvas->mapSettings().layerTransform( vlayer ) );
405+
if ( mCanvas->mapSettings().layerTransform( vlayer ).isValid() )
406+
rbGeom->transform( mCanvas->mapSettings().layerTransform( vlayer ) );
407407
mSelectRubberBand->setGeometry( rbGeom );
408408
}
409409
else

src/app/qgisapp.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6177,12 +6177,12 @@ void QgisApp::saveAsVectorFileGeneral( QgsVectorLayer* vlayer, bool symbologyOpt
61776177
bool autoGeometryType = dialog->automaticGeometryType();
61786178
QgsWKBTypes::Type forcedGeometryType = dialog->geometryType();
61796179

6180-
QgsCoordinateTransform* ct = nullptr;
6180+
QgsCoordinateTransform ct;
61816181
destCRS = QgsCRSCache::instance()->crsBySrsId( dialog->crs() );
61826182

61836183
if ( destCRS.isValid() && destCRS != vlayer->crs() )
61846184
{
6185-
ct = new QgsCoordinateTransform( vlayer->crs(), destCRS );
6185+
ct = QgsCoordinateTransform( vlayer->crs(), destCRS );
61866186

61876187
//ask user about datum transformation
61886188
QSettings settings;
@@ -6195,13 +6195,13 @@ void QgisApp::saveAsVectorFileGeneral( QgsVectorLayer* vlayer, bool symbologyOpt
61956195
QList< int > sdt = d.selectedDatumTransform();
61966196
if ( !sdt.isEmpty() )
61976197
{
6198-
ct->setSourceDatumTransform( sdt.at( 0 ) );
6198+
ct.setSourceDatumTransform( sdt.at( 0 ) );
61996199
}
62006200
if ( sdt.size() > 1 )
62016201
{
6202-
ct->setDestinationDatumTransform( sdt.at( 1 ) );
6202+
ct.setDestinationDatumTransform( sdt.at( 1 ) );
62036203
}
6204-
ct->initialise();
6204+
ct.initialise();
62056205
}
62066206
}
62076207
}
@@ -6235,8 +6235,6 @@ void QgisApp::saveAsVectorFileGeneral( QgsVectorLayer* vlayer, bool symbologyOpt
62356235
converterPtr
62366236
);
62376237

6238-
delete ct;
6239-
62406238
QApplication::restoreOverrideCursor();
62416239

62426240
if ( error == QgsVectorFileWriter::NoError )

src/core/composer/qgsatlascomposition.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ QgsGeometry QgsAtlasComposition::currentGeometry( const QgsCoordinateReferenceSy
925925
}
926926

927927
QgsGeometry transformed = *mCurrentFeature.constGeometry();
928-
transformed.transform( *QgsCoordinateTransformCache::instance()->transform( mCoverageLayer->crs().authid(), crs.authid() ) );
928+
transformed.transform( QgsCoordinateTransformCache::instance()->transform( mCoverageLayer->crs().authid(), crs.authid() ) );
929929
mGeometryCache[crs.srsid()] = transformed;
930930
return transformed;
931931
}

0 commit comments

Comments
 (0)