29 #include <QPushButton> 31 #if PROJ_VERSION_MAJOR>=6 38 if ( sourceCrs == destinationCrs )
47 QgsDatumTransformDialog dlg( sourceCrs, destinationCrs,
false,
true,
true, qMakePair( -1, -1 ), parent,
nullptr, QString(), mapCanvas );
48 if ( !windowTitle.isEmpty() )
49 dlg.setWindowTitle( windowTitle );
51 if ( dlg.shouldAskUserForSelection() )
71 dlg.applyDefaultTransform();
78 QPair<int, int> selectedDatumTransforms,
80 Qt::WindowFlags f,
const QString &selectedProj,
QgsMapCanvas *mapCanvas )
81 : QDialog( parent, f )
91 mLabelSrcDescription->setTextInteractionFlags( Qt::TextBrowserInteraction );
92 mLabelSrcDescription->setOpenExternalLinks(
true );
94 if ( !showMakeDefault )
95 mMakeDefaultCheckBox->setVisible(
false );
99 mButtonBox->removeButton( mButtonBox->button( QDialogButtonBox::Cancel ) );
100 setWindowFlags( windowFlags() | Qt::CustomizeWindowHint );
101 setWindowFlags( windowFlags() & ~Qt::WindowCloseButtonHint );
104 #if PROJ_VERSION_MAJOR>=6 105 mDatumTransformTableWidget->setColumnCount( 3 );
107 mDatumTransformTableWidget->setColumnCount( 2 );
111 #if PROJ_VERSION_MAJOR>=6 112 headers << tr(
"Transformation" ) << tr(
"Accuracy (meters)" ) << tr(
"Area of Use" );
114 headers << tr(
"Source Transform" ) << tr(
"Destination Transform" ) ;
116 mDatumTransformTableWidget->setHorizontalHeaderLabels( headers );
118 #if PROJ_VERSION_MAJOR>=6 123 if ( !destinationCrs.
isValid() )
125 if ( !destinationCrs.
isValid() )
132 mSourceProjectionSelectionWidget->setCrs( sourceCrs );
133 mDestinationProjectionSelectionWidget->setCrs( destinationCrs );
134 if ( !allowCrsChanges )
136 mCrsStackedWidget->setCurrentIndex( 1 );
137 mSourceProjectionSelectionWidget->setEnabled(
false );
138 mDestinationProjectionSelectionWidget->setEnabled(
false );
143 #if PROJ_VERSION_MAJOR<6 153 mainCanvasPoly << mainCanvasPoly.at( 0 );
174 #if PROJ_VERSION_MAJOR>=6 176 mHideDeprecatedCheckBox->setVisible(
false );
178 #if PROJ_VERSION_MAJOR>6 || PROJ_VERSION_MINOR>=2 179 mShowSupersededCheckBox->setVisible(
true );
181 mShowSupersededCheckBox->setVisible(
false );
184 mLabelDstDescription->hide();
186 mShowSupersededCheckBox->setVisible(
false );
188 mHideDeprecatedCheckBox->setChecked( settings.
value( QStringLiteral(
"Windows/DatumTransformDialog/hideDeprecated" ),
true ).toBool() );
191 connect( mHideDeprecatedCheckBox, &QCheckBox::stateChanged,
this, [ = ] { load(); } );
192 connect( mShowSupersededCheckBox, &QCheckBox::toggled,
this, &QgsDatumTransformDialog::showSupersededToggled );
193 connect( mDatumTransformTableWidget, &QTableWidget::currentItemChanged,
this, &QgsDatumTransformDialog::tableCurrentItemChanged );
199 mSourceCrs = sourceCrs;
200 mDestinationCrs = destinationCrs;
201 #if PROJ_VERSION_MAJOR>=6 208 mLabelSrcDescription->clear();
209 mLabelDstDescription->clear();
211 connect( mButtonBox, &QDialogButtonBox::helpRequested,
this, [ = ]
213 QgsHelp::openHelp( QStringLiteral(
"working_with_projections/working_with_projections.html" ) );
216 load( selectedDatumTransforms, selectedProj );
219 void QgsDatumTransformDialog::load( QPair<int, int> selectedDatumTransforms,
const QString &selectedProj )
221 mDatumTransformTableWidget->setRowCount( 0 );
224 int preferredInitialRow = -1;
225 #if PROJ_VERSION_MAJOR>=6 226 Q_UNUSED( selectedDatumTransforms )
229 std::unique_ptr< QTableWidgetItem > item = qgis::make_unique< QTableWidgetItem >();
230 item->setData( ProjRole, transform.proj );
231 item->setData( AvailableRole, transform.isAvailable );
232 item->setFlags( item->flags() & ~Qt::ItemIsEditable );
234 QString name = transform.name;
235 if ( !transform.authority.isEmpty() && !transform.code.isEmpty() )
236 name += QStringLiteral(
" — %1:%2" ).arg( transform.authority, transform.code );
237 item->setText( name );
241 QFont f = item->font();
244 item->setForeground( QBrush( QColor( 0, 120, 0 ) ) );
247 if ( !transform.isAvailable )
249 item->setForeground( QBrush( palette().color( QPalette::Disabled, QPalette::Text ) ) );
252 if ( preferredInitialRow < 0 && transform.isAvailable )
255 preferredInitialRow = row;
258 QString missingMessage;
259 if ( !transform.isAvailable )
261 QStringList gridMessages;
266 QString m = tr(
"This transformation requires the grid file “%1”, which is not available for use on the system." ).arg( grid.
shortName );
267 if ( !grid.
url.isEmpty() )
271 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 );
275 m +=
' ' + tr(
"This grid is available for download from <a href=\"%1\">%1</a>." ).arg( grid.
url );
282 if ( gridMessages.count() > 1 )
284 for (
int k = 0; k < gridMessages.count(); ++k )
285 gridMessages[k] = QStringLiteral(
"<li>%1</li>" ).arg( gridMessages.at( k ) );
287 missingMessage = QStringLiteral(
"<ul>%1</ul" ).arg( gridMessages.join( QString() ) );
289 else if ( !gridMessages.empty() )
291 missingMessage = gridMessages.constFirst();
295 QStringList areasOfUse;
296 QStringList authorityCodes;
298 #if PROJ_VERSION_MAJOR > 6 || PROJ_VERSION_MINOR >= 2 303 if ( !singleOpDetails.
scope.isEmpty() )
305 text += QStringLiteral(
"<b>%1</b>: %2" ).arg( tr(
"Scope" ), formatScope( singleOpDetails.
scope ) );
307 if ( !singleOpDetails.
remarks.isEmpty() )
309 if ( !text.isEmpty() )
310 text += QStringLiteral(
"<br>" );
311 text += QStringLiteral(
"<b>%1</b>: %2" ).arg( tr(
"Remarks" ), singleOpDetails.
remarks );
313 if ( !singleOpDetails.
areaOfUse.isEmpty() )
315 if ( !areasOfUse.contains( singleOpDetails.
areaOfUse ) )
318 if ( !singleOpDetails.
authority.isEmpty() && !singleOpDetails.
code.isEmpty() )
320 const QString identifier = QStringLiteral(
"%1:%2" ).arg( singleOpDetails.
authority, singleOpDetails.
code );
321 if ( !authorityCodes.contains( identifier ) )
322 authorityCodes << identifier;
325 if ( !text.isEmpty() )
327 opText.append( text );
332 if ( !transform.scope.isEmpty() )
334 text += QStringLiteral(
"<b>%1</b>: %2" ).arg( tr(
"Scope" ), transform.scope );
336 if ( !transform.remarks.isEmpty() )
338 if ( !text.isEmpty() )
339 text += QStringLiteral(
"<br>" );
340 text += QStringLiteral(
"<b>%1</b>: %2" ).arg( tr(
"Remarks" ), transform.remarks );
342 if ( !text.isEmpty() )
344 opText.append( text );
347 if ( opText.count() > 1 )
349 for (
int k = 0; k < opText.count(); ++k )
350 opText[k] = QStringLiteral(
"<li>%1</li>" ).arg( opText.at( k ) );
354 if ( !transform.areaOfUse.isEmpty() && !areasOfUse.contains( transform.areaOfUse ) )
355 areasOfUse << transform.areaOfUse;
356 item->setData( BoundsRole, transform.bounds );
358 const QString
id = !transform.authority.isEmpty() && !transform.code.isEmpty() ? QStringLiteral(
"%1:%2" ).arg( transform.authority, transform.code ) : QString();
359 if ( !
id.isEmpty() && !authorityCodes.contains(
id ) )
360 authorityCodes <<
id;
362 #if PROJ_VERSION_MAJOR > 6 || PROJ_VERSION_MINOR >= 2 363 const QColor disabled = palette().color( QPalette::Disabled, QPalette::Text );
364 const QColor active = palette().color( QPalette::Active, QPalette::Text );
366 const QColor codeColor( static_cast< int >( active.red() * 0.6 + disabled.red() * 0.4 ),
367 static_cast< int >( active.green() * 0.6 + disabled.green() * 0.4 ),
368 static_cast< int >( active.blue() * 0.6 + disabled.blue() * 0.4 ) );
369 const QString toolTipString = QStringLiteral(
"<b>%1</b>" ).arg( transform.name )
370 + ( !opText.empty() ? ( opText.count() == 1 ? QStringLiteral(
"<p>%1</p>" ).arg( opText.at( 0 ) ) : QStringLiteral(
"<ul>%1</ul>" ).arg( opText.join( QString() ) ) ) : QString() )
371 + ( !areasOfUse.empty() ? QStringLiteral(
"<p><b>%1</b>: %2</p>" ).arg( tr(
"Area of use" ), areasOfUse.join( QStringLiteral(
", " ) ) ) : QString() )
372 + ( !authorityCodes.empty() ? QStringLiteral(
"<p><b>%1</b>: %2</p>" ).arg( tr(
"Identifiers" ), authorityCodes.join( QStringLiteral(
", " ) ) ) : QString() )
373 + ( !missingMessage.isEmpty() ? QStringLiteral(
"<p><b style=\"color: red\">%1</b></p>" ).arg( missingMessage ) : QString() )
374 + QStringLiteral(
"<p><code style=\"color: %1\">%2</code></p>" ).arg( codeColor.name(), transform.proj );
376 const QString toolTipString = QStringLiteral(
"<b>%1</b>%2%3%4<p><code>%5</code></p>" ).arg( transform.name,
377 ( !transform.areaOfUse.isEmpty() ? QStringLiteral(
"<p><b>%1</b>: %2</p>" ).arg( tr(
"Area of use" ), transform.areaOfUse ) : QString() ),
378 ( !
id.isEmpty() ? QStringLiteral(
"<p><b>%1</b>: %2</p>" ).arg( tr(
"Identifier" ),
id ) : QString() ),
379 ( !missingMessage.isEmpty() ? QStringLiteral(
"<p><b style=\"color: red\">%1</b></p>" ).arg( missingMessage ) : QString() ),
382 item->setToolTip( toolTipString );
383 mDatumTransformTableWidget->setRowCount( row + 1 );
384 mDatumTransformTableWidget->setItem( row, 0, item.release() );
386 item = qgis::make_unique< QTableWidgetItem >();
387 item->setFlags( item->flags() & ~Qt::ItemIsEditable );
388 item->setText( transform.accuracy >= 0 ? QString::number( transform.accuracy ) : tr(
"Unknown" ) );
389 item->setToolTip( toolTipString );
390 if ( !transform.isAvailable )
392 item->setForeground( QBrush( palette().color( QPalette::Disabled, QPalette::Text ) ) );
394 mDatumTransformTableWidget->setItem( row, 1, item.release() );
396 #if PROJ_VERSION_MAJOR>=6 398 item = qgis::make_unique< QTableWidgetItem >();
399 item->setFlags( item->flags() & ~Qt::ItemIsEditable );
400 item->setText( areasOfUse.join( QStringLiteral(
", " ) ) );
401 item->setToolTip( toolTipString );
402 if ( !transform.isAvailable )
404 item->setForeground( QBrush( palette().color( QPalette::Disabled, QPalette::Text ) ) );
406 mDatumTransformTableWidget->setItem( row, 2, item.release() );
409 if ( transform.proj == selectedProj )
411 mDatumTransformTableWidget->selectRow( row );
417 Q_UNUSED( selectedProj )
422 bool itemDisabled =
false;
423 bool itemHidden =
false;
425 if ( transform.sourceTransformId == -1 && transform.destinationTransformId == -1 )
430 for (
int i = 0; i < 2; ++i )
432 std::unique_ptr< QTableWidgetItem > item = qgis::make_unique< QTableWidgetItem >();
433 int nr = i == 0 ? transform.sourceTransformId : transform.destinationTransformId;
434 item->setData( TransformIdRole, nr );
435 item->setFlags( item->flags() & ~Qt::ItemIsEditable );
446 itemHidden = mHideDeprecatedCheckBox->isChecked();
447 item->setForeground( QBrush( QColor( 255, 0, 0 ) ) );
452 QFont f = item->font();
455 item->setForeground( QBrush( QColor( 0, 120, 0 ) ) );
461 preferredInitialRow = row;
464 QString toolTipString;
465 if ( gridShiftTransformation( item->text() ) )
467 toolTipString.append( QStringLiteral(
"<p><b>NTv2</b></p>" ) );
471 toolTipString.append( QStringLiteral(
"<p><b>EPSG Transformations Code:</b> %1</p>" ).arg( info.
epsgCode ) );
476 toolTipString.append( QStringLiteral(
"<p><b>Remarks:</b> %1</p>" ).arg( info.
remarks ) );
477 if ( !info.
scope.isEmpty() )
478 toolTipString.append( QStringLiteral(
"<p><b>Scope:</b> %1</p>" ).arg( info.
scope ) );
480 toolTipString.append(
"<p><b>Preferred transformation</b></p>" );
482 toolTipString.append(
"<p><b>Deprecated transformation</b></p>" );
484 item->setToolTip( toolTipString );
486 if ( gridShiftTransformation( item->text() ) && !testGridShiftFileAvailability( item.get() ) )
495 item->setFlags( Qt::NoItemFlags );
497 mDatumTransformTableWidget->setRowCount( row + 1 );
498 mDatumTransformTableWidget->setItem( row, i, item.release() );
502 if ( ( transform.sourceTransformId == selectedDatumTransforms.first &&
503 transform.destinationTransformId == selectedDatumTransforms.second ) ||
504 ( transform.sourceTransformId == selectedDatumTransforms.second &&
505 transform.destinationTransformId == selectedDatumTransforms.first ) )
507 mDatumTransformTableWidget->selectRow( row );
515 if ( mDatumTransformTableWidget->currentRow() < 0 )
516 mDatumTransformTableWidget->selectRow( preferredInitialRow >= 0 ? preferredInitialRow : 0 );
518 mDatumTransformTableWidget->resizeColumnsToContents();
520 tableCurrentItemChanged(
nullptr,
nullptr );
523 void QgsDatumTransformDialog::setOKButtonEnabled()
525 int row = mDatumTransformTableWidget->currentRow();
526 #if PROJ_VERSION_MAJOR>=6 527 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( mSourceCrs.
isValid() && mDestinationCrs.
isValid()
528 && mDatumTransformTableWidget->item( row, 0 ) && mDatumTransformTableWidget->item( row, 0 )->data( AvailableRole ).toBool() );
530 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( mSourceCrs.
isValid() && mDestinationCrs.
isValid() && row >= 0 );
537 settings.
setValue( QStringLiteral(
"Windows/DatumTransformDialog/hideDeprecated" ), mHideDeprecatedCheckBox->isChecked() );
539 for (
int i = 0; i < 2; i++ )
541 settings.
setValue( QStringLiteral(
"Windows/DatumTransformDialog/columnWidths/%1" ).arg( i ), mDatumTransformTableWidget->columnWidth( i ) );
547 if ( mMakeDefaultCheckBox->isChecked() && !mDatumTransformTableWidget->selectedItems().isEmpty() )
550 settings.
beginGroup( QStringLiteral(
"/Projections" ) );
557 QString sourceDatumProj;
559 if ( sourceDatumTransform >= 0 )
562 QString destinationDatumProj;
563 if ( destinationDatumTransform >= 0 )
566 settings.
setValue( srcAuthId + QStringLiteral(
"//" ) + destAuthId + QStringLiteral(
"_srcTransform" ), sourceDatumProj );
567 settings.
setValue( srcAuthId + QStringLiteral(
"//" ) + destAuthId + QStringLiteral(
"_destTransform" ), destinationDatumProj );
568 settings.
setValue( srcAuthId + QStringLiteral(
"//" ) + destAuthId + QStringLiteral(
"_coordinateOp" ), dt.
proj );
575 if ( !mButtonBox->button( QDialogButtonBox::Cancel ) )
581 bool QgsDatumTransformDialog::shouldAskUserForSelection()
const 583 if ( mDatumTransforms.count() > 1 )
597 #if PROJ_VERSION_MAJOR>=6 601 if ( transform.isAvailable )
603 preferred.
proj = transform.proj;
610 preferredNonDeprecated.
sourceCrs = mSourceCrs;
612 bool foundPreferredNonDeprecated =
false;
613 bool foundPreferred =
false;
617 bool foundNonDeprecated =
false;
621 bool foundFallback =
false;
626 if ( transform.sourceTransformId == -1 && transform.destinationTransformId == -1 )
631 if ( !foundPreferredNonDeprecated && ( ( srcInfo.
preferred && !srcInfo.
deprecated ) || transform.sourceTransformId == -1 )
632 && ( ( destInfo.
preferred && !destInfo.
deprecated ) || transform.destinationTransformId == -1 ) )
636 foundPreferredNonDeprecated =
true;
638 else if ( !foundPreferred && ( srcInfo.
preferred || transform.sourceTransformId == -1 ) &&
639 ( destInfo.
preferred || transform.destinationTransformId == -1 ) )
643 foundPreferred =
true;
645 else if ( !foundNonDeprecated && ( !srcInfo.
deprecated || transform.sourceTransformId == -1 )
646 && ( !destInfo.
deprecated || transform.destinationTransformId == -1 ) )
650 foundNonDeprecated =
true;
652 else if ( !foundFallback )
656 foundFallback =
true;
660 if ( foundPreferredNonDeprecated )
661 return preferredNonDeprecated;
662 else if ( foundPreferred )
664 else if ( foundNonDeprecated )
665 return nonDeprecated;
671 void QgsDatumTransformDialog::applyDefaultTransform()
673 if ( mDatumTransforms.count() > 0 )
681 #if PROJ_VERSION_MAJOR>=6 691 QString QgsDatumTransformDialog::formatScope(
const QString &s )
695 QRegularExpression reGNSS( QStringLiteral(
"\\bGNSS\\b" ) );
696 scope.replace( reGNSS, QObject::tr(
"GNSS (Global Navigation Satellite System)" ) );
698 QRegularExpression reCORS( QStringLiteral(
"\\bCORS\\b" ) );
699 scope.replace( reCORS, QObject::tr(
"CORS (Continually Operating Reference Station)" ) );
706 int row = mDatumTransformTableWidget->currentRow();
713 QTableWidgetItem *srcItem = mDatumTransformTableWidget->item( row, 0 );
715 QTableWidgetItem *destItem = mDatumTransformTableWidget->item( row, 1 );
717 sdt.
proj = srcItem ? srcItem->data( ProjRole ).toString() : QString();
723 sdt.
proj = QString();
728 bool QgsDatumTransformDialog::gridShiftTransformation(
const QString &itemText )
const 730 return !itemText.isEmpty() && !itemText.contains( QLatin1String(
"towgs84" ), Qt::CaseInsensitive );
733 bool QgsDatumTransformDialog::testGridShiftFileAvailability( QTableWidgetItem *item )
const 740 QString itemText = item->text();
741 if ( itemText.isEmpty() )
746 char *projLib = getenv(
"PROJ_LIB" );
752 QStringList itemEqualSplit = itemText.split(
'=' );
754 for (
int i = 1; i < itemEqualSplit.size(); ++i )
758 filename.append(
'=' );
760 filename.append( itemEqualSplit.at( i ) );
763 QDir projDir( projLib );
764 if ( projDir.exists() )
767 QStringList fileList = projDir.entryList();
768 QStringList::const_iterator fileIt = fileList.constBegin();
769 for ( ; fileIt != fileList.constEnd(); ++fileIt )
771 #if defined(Q_OS_WIN) 772 if ( fileIt->compare( filename, Qt::CaseInsensitive ) == 0 )
774 if ( fileIt->compare( filename ) == 0 )
780 item->setToolTip( tr(
"File '%1' not found in directory '%2'" ).arg( filename, projDir.absolutePath() ) );
786 void QgsDatumTransformDialog::tableCurrentItemChanged( QTableWidgetItem *, QTableWidgetItem * )
788 int row = mDatumTransformTableWidget->currentRow();
791 mLabelSrcDescription->clear();
792 mLabelDstDescription->clear();
793 #if PROJ_VERSION_MAJOR>=6 799 QTableWidgetItem *srcItem = mDatumTransformTableWidget->item( row, 0 );
800 mLabelSrcDescription->setText( srcItem ? srcItem->toolTip() : QString() );
811 mAreaCanvas->setPreviewRect( rect );
812 #if PROJ_VERSION_MAJOR>=6 819 #if PROJ_VERSION_MAJOR>=6 823 QTableWidgetItem *destItem = mDatumTransformTableWidget->item( row, 1 );
824 mLabelDstDescription->setText( destItem ? destItem->toolTip() : QString() );
827 setOKButtonEnabled();
832 mSourceCrs = sourceCrs;
833 #if PROJ_VERSION_MAJOR>=6 841 setOKButtonEnabled();
846 mDestinationCrs = destinationCrs;
847 #if PROJ_VERSION_MAJOR>=6 855 setOKButtonEnabled();
858 void QgsDatumTransformDialog::showSupersededToggled(
bool )
860 #if PROJ_VERSION_MAJOR>=6 868 setOKButtonEnabled();
A rectangle specified with double values.
void removeCoordinateOperation(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs)
Removes the coordinate operation for the specified sourceCrs and destinationCrs.
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.
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.
#define Q_NOWARN_DEPRECATED_PUSH
A geometry is the spatial representation of a feature.
const QgsCoordinateReferenceSystem & crs
Map canvas is a class for displaying all GIS data types on a canvas.
bool addCoordinateOperation(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QString &coordinateOperationProjString)
Adds a new coordinateOperationProjString to use when projecting coordinates from the specified source...
static Q_INVOKABLE QgsCoordinateReferenceSystem fromEpsgId(long epsg)
Creates a CRS from a given EPSG ID.
QgsGeometry densifyByCount(int extraNodesPerSegment) const
Returns a copy of the geometry which has been densified by adding the specified number of extra nodes...
QgsCoordinateReferenceSystem crs
QgsRectangle intersect(const QgsRectangle &rect) const
Returns the intersection with the given rectangle.
Contains information about the context in which a coordinate transform is executed.
Q_DECL_DEPRECATED bool addSourceDestinationDatumTransform(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, int sourceTransformId, int destinationTransformId)
Adds a new sourceTransform and destinationTransform to use when projecting coordinates from the speci...
QgsCoordinateTransformContext transformContext
const QgsMapSettings & mapSettings() const
Gets access to properties used for map rendering.
void beginGroup(const QString &prefix, QgsSettings::Section section=QgsSettings::NoSection)
Appends prefix to the current group.
#define Q_NOWARN_DEPRECATED_POP
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
This class represents a coordinate reference system (CRS).
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the project's coordinate transform context, which stores various information regarding which dat...
static QgsGeometry fromQPolygonF(const QPolygonF &polygon)
Construct geometry from a QPolygonF.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Custom exception class for Coordinate Reference System related exceptions.
QPolygonF visiblePolygon() const
Returns the visible area as a polygon (may be rotated)
QgsRectangle bounds() const
Returns the approximate bounds for the region the CRS is usable within.
Temporarily removes all cursor overrides for the QApplication for the lifetime of the object...
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...
QString authid() const
Returns the authority identifier for the CRS.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.