30 #include <QPushButton>
31 #include <QRegularExpression>
33 #if PROJ_VERSION_MAJOR>=6
43 mLabelSrcDescription->setTextInteractionFlags( Qt::TextBrowserInteraction );
44 mLabelSrcDescription->setOpenExternalLinks(
true );
45 mInstallGridButton->hide();
47 #if PROJ_VERSION_MAJOR>=6
48 connect( mInstallGridButton, &QPushButton::clicked,
this, &QgsCoordinateOperationWidget::installGrid );
49 connect( mAllowFallbackCheckBox, &QCheckBox::toggled,
this, [ = ]
54 mCoordinateOperationTableWidget->setColumnCount( 3 );
56 mCoordinateOperationTableWidget->setColumnCount( 2 );
60 #if PROJ_VERSION_MAJOR>=6
61 headers << tr(
"Transformation" ) << tr(
"Accuracy (meters)" ) << tr(
"Area of Use" );
63 headers << tr(
"Source Transform" ) << tr(
"Destination Transform" ) ;
65 mCoordinateOperationTableWidget->setHorizontalHeaderLabels( headers );
67 #if PROJ_VERSION_MAJOR<6
71 #if PROJ_VERSION_MAJOR>=6
73 mHideDeprecatedCheckBox->setVisible(
false );
74 mShowSupersededCheckBox->setVisible(
true );
75 mLabelDstDescription->hide();
77 mShowSupersededCheckBox->setVisible(
false );
78 mAllowFallbackCheckBox->setVisible(
false );
80 mHideDeprecatedCheckBox->setChecked( settings.
value( QStringLiteral(
"Windows/DatumTransformDialog/hideDeprecated" ),
true ).toBool() );
83 connect( mHideDeprecatedCheckBox, &QCheckBox::stateChanged,
this, [ = ] { loadAvailableOperations(); } );
84 connect( mShowSupersededCheckBox, &QCheckBox::toggled,
this, &QgsCoordinateOperationWidget::showSupersededToggled );
85 connect( mCoordinateOperationTableWidget, &QTableWidget::currentItemChanged,
this, &QgsCoordinateOperationWidget::tableCurrentItemChanged );
88 mLabelSrcDescription->clear();
89 mLabelDstDescription->clear();
94 #if PROJ_VERSION_MAJOR<6
103 mainCanvasPoly << mainCanvasPoly.at( 0 );
127 mMakeDefaultCheckBox->setVisible( show );
132 return mMakeDefaultCheckBox->isChecked();
137 return !mCoordinateOperationTableWidget->selectedItems().isEmpty();
142 QList<QgsCoordinateOperationWidget::OperationDetails> res;
143 res.reserve( mDatumTransforms.size() );
144 #if PROJ_VERSION_MAJOR>=6
148 op.
proj = details.proj;
166 void QgsCoordinateOperationWidget::loadAvailableOperations()
168 mCoordinateOperationTableWidget->setRowCount( 0 );
171 int preferredInitialRow = -1;
172 #if PROJ_VERSION_MAJOR>=6
175 std::unique_ptr< QTableWidgetItem > item = qgis::make_unique< QTableWidgetItem >();
176 item->setData( ProjRole, transform.proj );
177 item->setData( AvailableRole, transform.isAvailable );
178 item->setFlags( item->flags() & ~Qt::ItemIsEditable );
180 QString name = transform.name;
181 if ( !transform.authority.isEmpty() && !transform.code.isEmpty() )
182 name += QStringLiteral(
" %1 %2:%3" ).arg( QString( QChar( 0x2013 ) ), transform.authority, transform.code );
183 item->setText( name );
187 QFont f = item->font();
190 item->setForeground( QBrush( QColor( 0, 120, 0 ) ) );
193 if ( !transform.isAvailable )
195 item->setForeground( QBrush( palette().color( QPalette::Disabled, QPalette::Text ) ) );
198 if ( preferredInitialRow < 0 && transform.isAvailable )
201 preferredInitialRow = row;
204 QString missingMessage;
205 if ( !transform.isAvailable )
207 QStringList gridMessages;
208 QStringList missingGrids;
209 QStringList missingGridPackages;
210 QStringList missingGridUrls;
218 missingGridUrls << grid.
url;
219 QString m = tr(
"This transformation requires the grid file “%1”, which is not available for use on the system." ).arg( grid.
shortName );
220 if ( !grid.
url.isEmpty() )
224 m +=
' ' + tr(
"This grid is part of the <i>%1</i> package, available for download from <a href=\"%2\">%2</a>." ).arg( grid.
packageName, grid.
url );
228 m +=
' ' + tr(
"This grid is available for download from <a href=\"%1\">%1</a>." ).arg( grid.
url );
235 item->setData( MissingGridsRole, missingGrids );
236 item->setData( MissingGridPackageNamesRole, missingGridPackages );
237 item->setData( MissingGridUrlsRole, missingGridUrls );
239 if ( gridMessages.count() > 1 )
241 for (
int k = 0; k < gridMessages.count(); ++k )
242 gridMessages[k] = QStringLiteral(
"<li>%1</li>" ).arg( gridMessages.at( k ) );
244 missingMessage = QStringLiteral(
"<ul>%1</ul" ).arg( gridMessages.join( QString() ) );
246 else if ( !gridMessages.empty() )
248 missingMessage = gridMessages.constFirst();
252 QStringList areasOfUse;
253 QStringList authorityCodes;
256 QString lastSingleOpScope;
257 QString lastSingleOpRemarks;
261 if ( !singleOpDetails.
scope.isEmpty() )
263 text += QStringLiteral(
"<b>%1</b>: %2" ).arg( tr(
"Scope" ), formatScope( singleOpDetails.
scope ) );
264 lastSingleOpScope = singleOpDetails.
scope;
266 if ( !singleOpDetails.
remarks.isEmpty() )
268 if ( !text.isEmpty() )
269 text += QLatin1String(
"<br>" );
270 text += QStringLiteral(
"<b>%1</b>: %2" ).arg( tr(
"Remarks" ), singleOpDetails.
remarks );
271 lastSingleOpRemarks = singleOpDetails.
remarks;
273 if ( !singleOpDetails.
areaOfUse.isEmpty() )
275 if ( !areasOfUse.contains( singleOpDetails.
areaOfUse ) )
278 if ( !singleOpDetails.
authority.isEmpty() && !singleOpDetails.
code.isEmpty() )
280 const QString identifier = QStringLiteral(
"%1:%2" ).arg( singleOpDetails.
authority, singleOpDetails.
code );
281 if ( !authorityCodes.contains( identifier ) )
282 authorityCodes << identifier;
285 if ( !text.isEmpty() )
287 opText.append( text );
292 if ( !transform.scope.isEmpty() && transform.scope != lastSingleOpScope )
294 text += QStringLiteral(
"<b>%1</b>: %2" ).arg( tr(
"Scope" ), transform.scope );
296 if ( !transform.remarks.isEmpty() && transform.remarks != lastSingleOpRemarks )
298 if ( !text.isEmpty() )
299 text += QLatin1String(
"<br>" );
300 text += QStringLiteral(
"<b>%1</b>: %2" ).arg( tr(
"Remarks" ), transform.remarks );
302 if ( !text.isEmpty() )
304 opText.append( text );
307 if ( opText.count() > 1 )
309 for (
int k = 0; k < opText.count(); ++k )
310 opText[k] = QStringLiteral(
"<li>%1</li>" ).arg( opText.at( k ) );
313 if ( !transform.areaOfUse.isEmpty() && !areasOfUse.contains( transform.areaOfUse ) )
314 areasOfUse << transform.areaOfUse;
315 item->setData( BoundsRole, transform.bounds );
317 const QString
id = !transform.authority.isEmpty() && !transform.code.isEmpty() ? QStringLiteral(
"%1:%2" ).arg( transform.authority, transform.code ) : QString();
318 if ( !
id.isEmpty() && !authorityCodes.contains(
id ) )
319 authorityCodes << id;
321 const QColor disabled = palette().color( QPalette::Disabled, QPalette::Text );
322 const QColor active = palette().color( QPalette::Active, QPalette::Text );
324 const QColor codeColor(
static_cast< int >( active.red() * 0.6 + disabled.red() * 0.4 ),
325 static_cast< int >( active.green() * 0.6 + disabled.green() * 0.4 ),
326 static_cast< int >( active.blue() * 0.6 + disabled.blue() * 0.4 ) );
327 const QString toolTipString = QStringLiteral(
"<b>%1</b>" ).arg( transform.name )
328 + ( !opText.empty() ? ( opText.count() == 1 ? QStringLiteral(
"<p>%1</p>" ).arg( opText.at( 0 ) ) : QStringLiteral(
"<ul>%1</ul>" ).arg( opText.join( QString() ) ) ) : QString() )
329 + ( !areasOfUse.empty() ? QStringLiteral(
"<p><b>%1</b>: %2</p>" ).arg( tr(
"Area of use" ), areasOfUse.join( QLatin1String(
", " ) ) ) : QString() )
330 + ( !authorityCodes.empty() ? QStringLiteral(
"<p><b>%1</b>: %2</p>" ).arg( tr(
"Identifiers" ), authorityCodes.join( QLatin1String(
", " ) ) ) : QString() )
331 + ( !missingMessage.isEmpty() ? QStringLiteral(
"<p><b style=\"color: red\">%1</b></p>" ).arg( missingMessage ) : QString() )
332 + QStringLiteral(
"<p><code style=\"color: %1\">%2</code></p>" ).arg( codeColor.name(), transform.proj );
334 item->setToolTip( toolTipString );
335 mCoordinateOperationTableWidget->setRowCount( row + 1 );
336 mCoordinateOperationTableWidget->setItem( row, 0, item.release() );
338 item = qgis::make_unique< QTableWidgetItem >();
339 item->setFlags( item->flags() & ~Qt::ItemIsEditable );
340 item->setText( transform.accuracy >= 0 ? QString::number( transform.accuracy ) : tr(
"Unknown" ) );
341 item->setToolTip( toolTipString );
342 if ( !transform.isAvailable )
344 item->setForeground( QBrush( palette().color( QPalette::Disabled, QPalette::Text ) ) );
346 mCoordinateOperationTableWidget->setItem( row, 1, item.release() );
348 #if PROJ_VERSION_MAJOR>=6
350 item = qgis::make_unique< QTableWidgetItem >();
351 item->setFlags( item->flags() & ~Qt::ItemIsEditable );
352 item->setText( areasOfUse.join( QLatin1String(
", " ) ) );
353 item->setToolTip( toolTipString );
354 if ( !transform.isAvailable )
356 item->setForeground( QBrush( palette().color( QPalette::Disabled, QPalette::Text ) ) );
358 mCoordinateOperationTableWidget->setItem( row, 2, item.release() );
367 bool itemDisabled =
false;
368 bool itemHidden =
false;
370 if ( transform.sourceTransformId == -1 && transform.destinationTransformId == -1 )
375 for (
int i = 0; i < 2; ++i )
377 std::unique_ptr< QTableWidgetItem > item = qgis::make_unique< QTableWidgetItem >();
378 int nr = i == 0 ? transform.sourceTransformId : transform.destinationTransformId;
379 item->setData( TransformIdRole, nr );
380 item->setFlags( item->flags() & ~Qt::ItemIsEditable );
391 itemHidden = mHideDeprecatedCheckBox->isChecked();
392 item->setForeground( QBrush( QColor( 255, 0, 0 ) ) );
397 QFont f = item->font();
400 item->setForeground( QBrush( QColor( 0, 120, 0 ) ) );
406 preferredInitialRow = row;
409 QString toolTipString;
410 if ( gridShiftTransformation( item->text() ) )
412 toolTipString.append( QStringLiteral(
"<p><b>NTv2</b></p>" ) );
416 toolTipString.append( QStringLiteral(
"<p><b>EPSG Transformations Code:</b> %1</p>" ).arg( info.
epsgCode ) );
421 toolTipString.append( QStringLiteral(
"<p><b>Remarks:</b> %1</p>" ).arg( info.
remarks ) );
422 if ( !info.
scope.isEmpty() )
423 toolTipString.append( QStringLiteral(
"<p><b>Scope:</b> %1</p>" ).arg( info.
scope ) );
425 toolTipString.append(
"<p><b>Preferred transformation</b></p>" );
427 toolTipString.append(
"<p><b>Deprecated transformation</b></p>" );
429 item->setToolTip( toolTipString );
431 if ( gridShiftTransformation( item->text() ) && !testGridShiftFileAvailability( item.get() ) )
440 item->setFlags( Qt::NoItemFlags );
442 mCoordinateOperationTableWidget->setRowCount( row + 1 );
443 mCoordinateOperationTableWidget->setItem( row, i, item.release() );
451 if ( mCoordinateOperationTableWidget->currentRow() < 0 )
452 mCoordinateOperationTableWidget->selectRow( preferredInitialRow >= 0 ? preferredInitialRow : 0 );
454 mCoordinateOperationTableWidget->resizeColumnsToContents();
456 tableCurrentItemChanged(
nullptr,
nullptr );
462 settings.
setValue( QStringLiteral(
"Windows/DatumTransformDialog/hideDeprecated" ), mHideDeprecatedCheckBox->isChecked() );
464 for (
int i = 0; i < 2; i++ )
466 settings.
setValue( QStringLiteral(
"Windows/DatumTransformDialog/columnWidths/%1" ).arg( i ), mCoordinateOperationTableWidget->columnWidth( i ) );
474 #if PROJ_VERSION_MAJOR>=6
478 if ( transform.isAvailable )
480 preferred.
proj = transform.proj;
488 bool foundPreferredNonDeprecated =
false;
489 bool foundPreferred =
false;
491 bool foundNonDeprecated =
false;
493 bool foundFallback =
false;
498 if ( transform.sourceTransformId == -1 && transform.destinationTransformId == -1 )
503 if ( !foundPreferredNonDeprecated && ( ( srcInfo.
preferred && !srcInfo.
deprecated ) || transform.sourceTransformId == -1 )
504 && ( ( destInfo.
preferred && !destInfo.
deprecated ) || transform.destinationTransformId == -1 ) )
508 foundPreferredNonDeprecated =
true;
510 else if ( !foundPreferred && ( srcInfo.
preferred || transform.sourceTransformId == -1 ) &&
511 ( destInfo.
preferred || transform.destinationTransformId == -1 ) )
515 foundPreferred =
true;
517 else if ( !foundNonDeprecated && ( !srcInfo.
deprecated || transform.sourceTransformId == -1 )
518 && ( !destInfo.
deprecated || transform.destinationTransformId == -1 ) )
522 foundNonDeprecated =
true;
524 else if ( !foundFallback )
528 foundFallback =
true;
532 if ( foundPreferredNonDeprecated )
533 return preferredNonDeprecated;
534 else if ( foundPreferred )
536 else if ( foundNonDeprecated )
537 return nonDeprecated;
543 QString QgsCoordinateOperationWidget::formatScope(
const QString &s )
547 QRegularExpression reGNSS( QStringLiteral(
"\\bGNSS\\b" ) );
548 scope.replace( reGNSS, QObject::tr(
"GNSS (Global Navigation Satellite System)" ) );
550 QRegularExpression reCORS( QStringLiteral(
"\\bCORS\\b" ) );
551 scope.replace( reCORS, QObject::tr(
"CORS (Continually Operating Reference Station)" ) );
558 int row = mCoordinateOperationTableWidget->currentRow();
563 QTableWidgetItem *srcItem = mCoordinateOperationTableWidget->item( row, 0 );
565 QTableWidgetItem *destItem = mCoordinateOperationTableWidget->item( row, 1 );
567 op.
proj = srcItem ? srcItem->data( ProjRole ).toString() : QString();
568 op.
isAvailable = srcItem ? srcItem->data( AvailableRole ).toBool() :
true;
582 int prevRow = mCoordinateOperationTableWidget->currentRow();
584 for (
int row = 0; row < mCoordinateOperationTableWidget->rowCount(); ++row )
586 QTableWidgetItem *srcItem = mCoordinateOperationTableWidget->item( row, 0 );
587 #if PROJ_VERSION_MAJOR>=6
588 if ( srcItem && srcItem->data( ProjRole ).toString() == operation.
proj )
590 mCoordinateOperationTableWidget->selectRow( row );
594 QTableWidgetItem *destItem = mCoordinateOperationTableWidget->item( row, 1 );
597 if ( ( srcItem && destItem && operation.
sourceTransformId == srcItem->data( TransformIdRole ).toInt() &&
599 || ( srcItem && destItem && operation.
destinationTransformId == srcItem->data( TransformIdRole ).toInt() &&
601 || ( srcItem && !destItem && operation.
sourceTransformId == srcItem->data( TransformIdRole ).toInt() &&
603 || ( !srcItem && destItem && operation.
destinationTransformId == destItem->data( TransformIdRole ).toInt() &&
605 || ( srcItem && !destItem && operation.
destinationTransformId == srcItem->data( TransformIdRole ).toInt() &&
607 || ( !srcItem && destItem && operation.
sourceTransformId == destItem->data( TransformIdRole ).toInt() &&
611 mCoordinateOperationTableWidget->selectRow( row );
617 bool fallbackChanged = mAllowFallbackCheckBox->isChecked() != operation.
allowFallback;
618 mAllowFallbackCheckBox->setChecked( operation.
allowFallback );
621 if ( mCoordinateOperationTableWidget->currentRow() != prevRow || fallbackChanged )
627 #if PROJ_VERSION_MAJOR>=6
642 if ( context.
hasTransform( mSourceCrs, mDestinationCrs ) )
649 deets.destinationTransformId = op.destinationTransformId;
661 mAllowFallbackCheckBox->setVisible( visible );
664 bool QgsCoordinateOperationWidget::gridShiftTransformation(
const QString &itemText )
const
666 return !itemText.isEmpty() && !itemText.contains( QLatin1String(
"towgs84" ), Qt::CaseInsensitive );
669 bool QgsCoordinateOperationWidget::testGridShiftFileAvailability( QTableWidgetItem *item )
const
676 QString itemText = item->text();
677 if ( itemText.isEmpty() )
682 char *projLib = getenv(
"PROJ_LIB" );
688 QStringList itemEqualSplit = itemText.split(
'=' );
690 for (
int i = 1; i < itemEqualSplit.size(); ++i )
694 filename.append(
'=' );
696 filename.append( itemEqualSplit.at( i ) );
699 QDir projDir( projLib );
700 if ( projDir.exists() )
703 QStringList fileList = projDir.entryList();
704 QStringList::const_iterator fileIt = fileList.constBegin();
705 for ( ; fileIt != fileList.constEnd(); ++fileIt )
707 #if defined(Q_OS_WIN)
708 if ( fileIt->compare( filename, Qt::CaseInsensitive ) == 0 )
710 if ( fileIt->compare( filename ) == 0 )
716 item->setToolTip( tr(
"File '%1' not found in directory '%2'" ).arg( filename, projDir.absolutePath() ) );
722 void QgsCoordinateOperationWidget::tableCurrentItemChanged( QTableWidgetItem *, QTableWidgetItem * )
724 int row = mCoordinateOperationTableWidget->currentRow();
727 mLabelSrcDescription->clear();
728 mLabelDstDescription->clear();
729 #if PROJ_VERSION_MAJOR>=6
731 mInstallGridButton->hide();
736 QTableWidgetItem *srcItem = mCoordinateOperationTableWidget->item( row, 0 );
737 mLabelSrcDescription->setText( srcItem ? srcItem->toolTip() : QString() );
748 mAreaCanvas->setPreviewRect( rect );
749 #if PROJ_VERSION_MAJOR>=6
752 const QStringList missingGrids = srcItem->data( MissingGridsRole ).toStringList();
753 mInstallGridButton->setVisible( !missingGrids.empty() );
754 if ( !missingGrids.empty() )
756 mInstallGridButton->setText( tr(
"Install “%1” Grid…" ).arg( missingGrids.at( 0 ) ) );
763 #if PROJ_VERSION_MAJOR>=6
765 mInstallGridButton->hide();
768 QTableWidgetItem *destItem = mCoordinateOperationTableWidget->item( row, 1 );
769 mLabelDstDescription->setText( destItem ? destItem->toolTip() : QString() );
772 #if PROJ_VERSION_MAJOR>=6
773 if ( newOp.proj != mPreviousOp.
proj && !mBlockSignals )
786 #if PROJ_VERSION_MAJOR>=6
793 loadAvailableOperations();
799 #if PROJ_VERSION_MAJOR>=6
806 loadAvailableOperations();
809 void QgsCoordinateOperationWidget::showSupersededToggled(
bool )
811 #if PROJ_VERSION_MAJOR>=6
818 loadAvailableOperations();
821 void QgsCoordinateOperationWidget::installGrid()
823 #if PROJ_VERSION_MAJOR>=6
824 int row = mCoordinateOperationTableWidget->currentRow();
825 QTableWidgetItem *srcItem = mCoordinateOperationTableWidget->item( row, 0 );
829 const QStringList missingGrids = srcItem->data( MissingGridsRole ).toStringList();
830 if ( missingGrids.empty() )
833 const QStringList missingGridPackagesNames = srcItem->data( MissingGridPackageNamesRole ).toStringList();
834 const QString packageName = missingGridPackagesNames.value( 0 );
835 const QStringList missingGridUrls = srcItem->data( MissingGridUrlsRole ).toStringList();
836 const QString gridUrl = missingGridUrls.value( 0 );
838 QString downloadMessage;
839 if ( !packageName.isEmpty() )
841 downloadMessage = tr(
"This grid is part of the “<i>%1</i>” package, available for download from <a href=\"%2\">%2</a>." ).arg( packageName, gridUrl );
843 else if ( !gridUrl.isEmpty() )
845 downloadMessage = tr(
"This grid is available for download from <a href=\"%1\">%1</a>." ).arg( gridUrl );
848 const QString longMessage = tr(
"<p>This transformation requires the grid file “%1”, which is not available for use on the system.</p>" ).arg( missingGrids.at( 0 ) );
850 QgsInstallGridShiftFileDialog *dlg =
new QgsInstallGridShiftFileDialog( missingGrids.at( 0 ),
this );
851 dlg->setAttribute( Qt::WA_DeleteOnClose );
852 dlg->setWindowTitle( tr(
"Install Grid File" ) );
853 dlg->setDescription( longMessage );
854 dlg->setDownloadMessage( downloadMessage );
This class represents a coordinate reference system (CRS).
QgsRectangle bounds() const
Returns the approximate bounds for the region the CRS is usable within.
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
Contains information about the context in which a coordinate transform is executed.
bool allowFallbackTransform(const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination) const
Returns true if approximate "ballpark" transforms may be used when transforming between a source and ...
QString calculateCoordinateOperation(const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination) const
Returns the Proj coordinate operation string to use when transforming from the specified source CRS t...
Q_DECL_DEPRECATED QgsDatumTransform::TransformPair calculateDatumTransforms(const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination) const
Returns the pair of source and destination datum transforms to use for a transform from the specified...
bool hasTransform(const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination) const
Returns true if the context has a valid coordinate operation to use when transforming from the specif...
Custom exception class for Coordinate Reference System related exceptions.
A geometry is the spatial representation of a feature.
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
OperationResult transform(const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection direction=QgsCoordinateTransform::ForwardTransform, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
Map canvas is a class for displaying all GIS data types on a canvas.
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
QPolygonF visiblePolygon() const
Returns the visible area as a polygon (may be rotated)
static QgsProject * instance()
Returns the QgsProject singleton instance.
A rectangle specified with double values.
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
This class is a composition of two QSettings instances:
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
#define Q_NOWARN_DEPRECATED_POP
#define Q_NOWARN_DEPRECATED_PUSH
const QgsCoordinateReferenceSystem & crs