Skip to content
Permalink
Browse files

Add a method for retrieving a user friendly descriptive string for

a CRS

And use this wherever we show CRS values to users

(cherry picked from commit fdf211a)
  • Loading branch information
nyalldawson committed Dec 18, 2019
1 parent 4d23887 commit b5e06925187eb621f9b5af867251df17c90738f1
@@ -645,17 +645,33 @@ internal QGIS CRS ID with "QGIS" authority, for example "QGIS:100005"

QString description() const;
%Docstring
Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94". In most
cases this is the best method to use when showing a friendly identifier for the CRS to a
user.

:return: descriptive name of the CRS
Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".

.. note::

an empty string will be returned if the description is not available for the CRS

.. seealso:: :py:func:`authid`

.. seealso:: :py:func:`userFriendlyIdentifier`
%End

QString userFriendlyIdentifier( bool shortString = false ) const;
%Docstring
Returns a user friendly identifier for the CRS.

Depending on the format of the CRS, this may reflect the CRSes registered name, or for
CRSes not saved in the database it may reflect the underlying WKT or Proj string definition
of the CRS.

In most cases this is the best method to use when showing a friendly identifier for the CRS to a
user.

If ``shortString`` is ``True`` than an abbreviated identifier will be returned.

.. seealso:: :py:func:`description`

.. versionadded:: 3.10.3
%End

QString projectionAcronym() const;
@@ -187,7 +187,7 @@ QVariantMap QgsRasterLayerUniqueValuesReportAlgorithm::processAlgorithm( const Q
out << QStringLiteral( "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/></head><body>\n" );
out << QStringLiteral( "<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( "Analyzed file" ), mSource, QObject::tr( "band" ) ).arg( mBand );
out << QObject::tr( "<p>%1: %2</p>\n" ).arg( QObject::tr( "Extent" ), mExtent.toString() );
out << QObject::tr( "<p>%1: %2 (%3)</p>\n" ).arg( QObject::tr( "Projection" ), mCrs.description(), mCrs.authid() );
out << QObject::tr( "<p>%1: %2</p>\n" ).arg( QObject::tr( "Projection" ), mCrs.userFriendlyIdentifier() );
out << QObject::tr( "<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( "Width in pixels" ) ).arg( mLayerWidth ).arg( QObject::tr( "units per pixel" ) ).arg( mRasterUnitsPerPixelX );
out << QObject::tr( "<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( "Height in pixels" ) ).arg( mLayerHeight ).arg( QObject::tr( "units per pixel" ) ).arg( mRasterUnitsPerPixelY );
out << QObject::tr( "<p>%1: %2</p>\n" ).arg( QObject::tr( "Total pixel count" ) ).arg( layerSize );
@@ -683,7 +683,7 @@ void QgisApp::validateCrs( QgsCoordinateReferenceSystem &srs )
{
srs.createFromOgcWmsCrs( QgsSettings().value( QStringLiteral( "Projections/layerDefaultCrs" ), GEO_EPSG_CRS_AUTHID ).toString() );
sAuthId = srs.authid();
visibleMessageBar()->pushMessage( tr( "CRS was undefined" ), tr( "defaulting to CRS %1 - %2" ).arg( sAuthId, srs.description() ), Qgis::Warning, messageTimeout() );
visibleMessageBar()->pushMessage( tr( "CRS was undefined" ), tr( "defaulting to CRS %1" ).arg( srs.userFriendlyIdentifier() ), Qgis::Warning, messageTimeout() );
break;
}

@@ -722,7 +722,7 @@ void QgisApp::validateCrs( QgsCoordinateReferenceSystem &srs )
srs = QgsProject::instance()->crs();
sAuthId = srs.authid();
QgsDebugMsg( "Layer srs set from project: " + sAuthId );
visibleMessageBar()->pushMessage( tr( "CRS was undefined" ), tr( "defaulting to project CRS %1 - %2" ).arg( sAuthId, srs.description() ), Qgis::Warning, messageTimeout() );
visibleMessageBar()->pushMessage( tr( "CRS was undefined" ), tr( "defaulting to project CRS %1" ).arg( srs.userFriendlyIdentifier() ), Qgis::Warning, messageTimeout() );
break;
}
}
@@ -12496,7 +12496,7 @@ void QgisApp::updateCrsStatusBar()
mOnTheFlyProjectionStatusButton->setText( QgsProject::instance()->crs().authid() );

mOnTheFlyProjectionStatusButton->setToolTip(
tr( "Current CRS: %1" ).arg( QgsProject::instance()->crs().description() ) );
tr( "Current CRS: %1" ).arg( QgsProject::instance()->crs().userFriendlyIdentifier() ) );
mOnTheFlyProjectionStatusButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconProjectionEnabled.svg" ) ) );
}
else
@@ -65,29 +65,13 @@ QgsAppMissingGridHandler::QgsAppMissingGridHandler( QObject *parent )

}

QString displayIdentifierForCrs( const QgsCoordinateReferenceSystem &crs, bool shortString = false )
{
if ( !crs.authid().isEmpty() )
{
if ( !shortString && !crs.description().isEmpty() )
return QStringLiteral( "%1 [%2]" ).arg( crs.authid(), crs.description() );
return crs.authid();
}
else if ( !crs.description().isEmpty() )
return crs.description();
else if ( !crs.toProj().isEmpty() )
return crs.toProj();
else
return crs.toWkt();
}

void QgsAppMissingGridHandler::onMissingRequiredGrid( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QgsDatumTransform::GridDetails &grid )
{
if ( !shouldWarnAboutPair( sourceCrs, destinationCrs ) )
return;

const QString shortMessage = tr( "No transform available between %1 and %2" ).arg( displayIdentifierForCrs( sourceCrs, true ),
displayIdentifierForCrs( destinationCrs, true ) );
const QString shortMessage = tr( "No transform available between %1 and %2" ).arg( sourceCrs.userFriendlyIdentifier( true ),
destinationCrs.userFriendlyIdentifier( true ) );

QString downloadMessage;
const QString gridName = grid.shortName;
@@ -104,8 +88,8 @@ void QgsAppMissingGridHandler::onMissingRequiredGrid( const QgsCoordinateReferen
}

const QString longMessage = tr( "<p>No transform is available between <i>%1</i> and <i>%2</i>.</p>"
"<p>This transformation requires the grid file “%3”, which is not available for use on the system.</p>" ).arg( displayIdentifierForCrs( sourceCrs ),
displayIdentifierForCrs( destinationCrs ),
"<p>This transformation requires the grid file “%3”, which is not available for use on the system.</p>" ).arg( sourceCrs.userFriendlyIdentifier(),
destinationCrs.userFriendlyIdentifier(),
grid.shortName );

QgsMessageBar *bar = QgisApp::instance()->messageBar();
@@ -133,8 +117,8 @@ void QgsAppMissingGridHandler::onMissingPreferredGrid( const QgsCoordinateRefere
if ( !shouldWarnAboutPair( sourceCrs, destinationCrs ) )
return;

const QString shortMessage = tr( "Cannot use preferred transform between %1 and %2" ).arg( displayIdentifierForCrs( sourceCrs, true ),
displayIdentifierForCrs( destinationCrs, true ) );
const QString shortMessage = tr( "Cannot use preferred transform between %1 and %2" ).arg( sourceCrs.userFriendlyIdentifier( true ),
destinationCrs.userFriendlyIdentifier( true ) );

QString gridMessage;
QString downloadMessage;
@@ -172,8 +156,8 @@ void QgsAppMissingGridHandler::onMissingPreferredGrid( const QgsCoordinateRefere
accuracyMessage = tr( "<p>Current transform “<i>%1</i>” has an unknown accuracy, while the preferred transformation “<i>%2</i>” has accuracy %3 meters.</p>" ).arg( availableOperation.name )
.arg( preferredOperation.name ).arg( preferredOperation.accuracy );

const QString longMessage = tr( "<p>The preferred transform between <i>%1</i> and <i>%2</i> is not available for use on the system.</p>" ).arg( displayIdentifierForCrs( sourceCrs ),
displayIdentifierForCrs( destinationCrs ) )
const QString longMessage = tr( "<p>The preferred transform between <i>%1</i> and <i>%2</i> is not available for use on the system.</p>" ).arg( sourceCrs.userFriendlyIdentifier(),
destinationCrs.userFriendlyIdentifier() )
+ gridMessage + accuracyMessage;

QgsMessageBar *bar = QgisApp::instance()->messageBar();
@@ -201,8 +185,8 @@ void QgsAppMissingGridHandler::onCoordinateOperationCreationError( const QgsCoor
if ( !shouldWarnAboutPairForCurrentProject( sourceCrs, destinationCrs ) )
return;

const QString shortMessage = tr( "No transform available between %1 and %2" ).arg( displayIdentifierForCrs( sourceCrs, true ), displayIdentifierForCrs( destinationCrs, true ) );
const QString longMessage = tr( "<p>No transform is available between <i>%1</i> and <i>%2</i>.</p><p style=\"color: red\">%3</p>" ).arg( displayIdentifierForCrs( sourceCrs ), displayIdentifierForCrs( destinationCrs ), error );
const QString shortMessage = tr( "No transform available between %1 and %2" ).arg( sourceCrs.userFriendlyIdentifier( true ), destinationCrs.userFriendlyIdentifier( true ) );
const QString longMessage = tr( "<p>No transform is available between <i>%1</i> and <i>%2</i>.</p><p style=\"color: red\">%3</p>" ).arg( sourceCrs.userFriendlyIdentifier(), destinationCrs.userFriendlyIdentifier(), error );

QgsMessageBar *bar = QgisApp::instance()->messageBar();
QgsMessageBarItem *widget = bar->createMessage( QString(), shortMessage );
@@ -225,8 +209,8 @@ void QgsAppMissingGridHandler::onMissingGridUsedByContextHandler( const QgsCoord
if ( !shouldWarnAboutPairForCurrentProject( sourceCrs, destinationCrs ) )
return;

const QString shortMessage = tr( "Cannot use project transform between %1 and %2" ).arg( displayIdentifierForCrs( sourceCrs, true ),
displayIdentifierForCrs( destinationCrs, true ) );
const QString shortMessage = tr( "Cannot use project transform between %1 and %2" ).arg( sourceCrs.userFriendlyIdentifier( true ),
destinationCrs.userFriendlyIdentifier( true ) );

QString gridMessage;
QString downloadMessage;
@@ -256,8 +240,8 @@ void QgsAppMissingGridHandler::onMissingGridUsedByContextHandler( const QgsCoord
gridMessage = "<ul>" + gridMessage + "</ul>";
}

const QString longMessage = tr( "<p>This project specifies a preset transform between <i>%1</i> and <i>%2</i>, which is not available for use on the system.</p>" ).arg( displayIdentifierForCrs( sourceCrs ),
displayIdentifierForCrs( destinationCrs ) )
const QString longMessage = tr( "<p>This project specifies a preset transform between <i>%1</i> and <i>%2</i>, which is not available for use on the system.</p>" ).arg( sourceCrs.userFriendlyIdentifier(),
destinationCrs.userFriendlyIdentifier() )
+ gridMessage
+ tr( "<p>The operation specified for use in the project is:</p><p><code>%1</code></p>" ).arg( desired.proj ) ;

@@ -387,7 +387,7 @@ void QgsMeasureDialog::updateUi()
{
//both source and destination units are degrees
toolTip += "<br> * " + tr( "Both project CRS (%1) and measured area are in degrees, so area is calculated using Cartesian calculations in square degrees." ).arg(
mCanvas->mapSettings().destinationCrs().description() );
mCanvas->mapSettings().destinationCrs().userFriendlyIdentifier() );
mDa.setEllipsoid( GEO_NONE );
mConvertToDisplayUnits = false; //not required since we will be measuring in degrees
}
@@ -406,7 +406,7 @@ void QgsMeasureDialog::updateUi()
resultUnit = QgsUnitTypes::distanceToAreaUnit( mCanvas->mapSettings().destinationCrs().mapUnits() );
toolTip += "<br> * " + tr( "Project ellipsoidal calculation is not selected." ) + ' ';
toolTip += tr( "Area is calculated in %1, based on project CRS (%2)." ).arg( QgsUnitTypes::toString( resultUnit ),
mCanvas->mapSettings().destinationCrs().description() );
mCanvas->mapSettings().destinationCrs().userFriendlyIdentifier() );
}
setWindowTitle( tr( "Measure" ) );

@@ -465,7 +465,7 @@ void QgsMeasureDialog::updateUi()
{
//both source and destination units are degrees
toolTip += "<br> * " + tr( "Both project CRS (%1) and measured length are in degrees, so distance is calculated using Cartesian calculations in degrees." ).arg(
mCanvas->mapSettings().destinationCrs().description() );
mCanvas->mapSettings().destinationCrs().userFriendlyIdentifier() );
mDa.setEllipsoid( GEO_NONE );
mConvertToDisplayUnits = false; //not required since we will be measuring in degrees
}
@@ -484,7 +484,7 @@ void QgsMeasureDialog::updateUi()
resultUnit = mCanvas->mapSettings().destinationCrs().mapUnits();
toolTip += "<br> * " + tr( "Project ellipsoidal calculation is not selected." ) + ' ';
toolTip += tr( "Distance is calculated in %1, based on project CRS (%2)." ).arg( QgsUnitTypes::toString( resultUnit ),
mCanvas->mapSettings().destinationCrs().description() );
mCanvas->mapSettings().destinationCrs().userFriendlyIdentifier() );
}
setWindowTitle( tr( "Measure" ) );

@@ -95,7 +95,7 @@ QgsNewSpatialiteLayerDialog::QgsNewSpatialiteLayerDialog( QWidget *parent, Qt::W

// Set the SRID box to a default of WGS84
mCrsId = defaultCrs.authid();
leSRID->setText( defaultCrs.authid() + " - " + defaultCrs.description() );
leSRID->setText( defaultCrs.userFriendlyIdentifier() );

pbnFindSRID->setEnabled( mDatabaseComboBox->count() );

@@ -255,7 +255,7 @@ void QgsNewSpatialiteLayerDialog::pbnFindSRID_clicked()
if ( crsId != mCrsId )
{
mCrsId = crsId;
leSRID->setText( srs.authid() + " - " + srs.description() );
leSRID->setText( srs.userFriendlyIdentifier() );
}
}
delete mySelector;
@@ -994,7 +994,7 @@ void QgsProjectProperties::apply()
QgsProject::instance()->setCrs( srs );
if ( srs.isValid() )
{
QgsDebugMsgLevel( QStringLiteral( "Selected CRS " ) + srs.description(), 4 );
QgsDebugMsgLevel( QStringLiteral( "Selected CRS " ) + srs.userFriendlyIdentifier(), 4 );
// write the currently selected projections _proj string_ to project settings
QgsDebugMsgLevel( QStringLiteral( "SpatialRefSys/ProjectCRSProj4String: %1" ).arg( srs.toProj() ), 4 );
}
@@ -66,7 +66,7 @@ QVariant QgsRecentProjectItemsModel::data( const QModelIndex &index, int role )
if ( !mRecentProjects.at( index.row() ).crs.isEmpty() )
{
QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( mRecentProjects.at( index.row() ).crs );
return QStringLiteral( "%1 (%2)" ).arg( mRecentProjects.at( index.row() ).crs, crs.description() );
return QStringLiteral( "%1 (%2)" ).arg( mRecentProjects.at( index.row() ).crs, crs.userFriendlyIdentifier() );
}
else
{
@@ -1164,6 +1164,24 @@ QString QgsCoordinateReferenceSystem::description() const
}
}

QString QgsCoordinateReferenceSystem::userFriendlyIdentifier( bool shortString ) const
{
if ( !authid().isEmpty() )
{
if ( !shortString && !description().isEmpty() )
return QStringLiteral( "%1 - %2" ).arg( authid(), description() );
return authid();
}
else if ( !description().isEmpty() )
return description();
else if ( !toWkt().isEmpty() )
return toWkt().left( 30 ) + QChar( 0x2026 );
else if ( !toProj().isEmpty() )
return toProj().left( 30 ) + QChar( 0x2026 );
else
return QString();
}

QString QgsCoordinateReferenceSystem::projectionAcronym() const
{
if ( d->mProjectionAcronym.isNull() )
@@ -603,15 +603,31 @@ class CORE_EXPORT QgsCoordinateReferenceSystem
QString authid() const;

/**
* Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94". In most
* cases this is the best method to use when showing a friendly identifier for the CRS to a
* user.
* \returns descriptive name of the CRS
* Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".
* \note an empty string will be returned if the description is not available for the CRS
* \see authid()
* \see userFriendlyIdentifier()
*/
QString description() const;

/**
* Returns a user friendly identifier for the CRS.
*
* Depending on the format of the CRS, this may reflect the CRSes registered name, or for
* CRSes not saved in the database it may reflect the underlying WKT or Proj string definition
* of the CRS.
*
* In most cases this is the best method to use when showing a friendly identifier for the CRS to a
* user.
*
* If \a shortString is TRUE than an abbreviated identifier will be returned.
*
* \see description()
* \since QGIS 3.10.3
*/
QString userFriendlyIdentifier( bool shortString = false ) const;

/**
* Returns the projection acronym for the projection used by the CRS.
* \returns the official Proj acronym for the projection family
@@ -600,8 +600,8 @@ QString QgsOWSSourceSelect::descriptionForAuthId( const QString &authId )
return mCrsNames[ authId ];

QgsCoordinateReferenceSystem qgisSrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( authId );
mCrsNames.insert( authId, qgisSrs.description() );
return qgisSrs.description();
mCrsNames.insert( authId, qgisSrs.userFriendlyIdentifier() );
return qgisSrs.userFriendlyIdentifier();
}

void QgsOWSSourceSelect::addDefaultServers()
@@ -272,11 +272,11 @@ void QgsProjectionSelectionWidget::setLayerCrs( const QgsCoordinateReferenceSyst
{
if ( layerItemIndex > -1 )
{
mCrsComboBox->setItemText( layerItemIndex, tr( "Layer CRS: %1 - %2" ).arg( crs.authid(), crs.description() ) );
mCrsComboBox->setItemText( layerItemIndex, tr( "Layer CRS: %1" ).arg( crs.userFriendlyIdentifier() ) );
}
else
{
mCrsComboBox->insertItem( firstRecentCrsIndex(), tr( "Layer CRS: %1 - %2" ).arg( crs.authid(), crs.description() ), QgsProjectionSelectionWidget::LayerCrs );
mCrsComboBox->insertItem( firstRecentCrsIndex(), tr( "Layer CRS: %1" ).arg( crs.userFriendlyIdentifier() ), QgsProjectionSelectionWidget::LayerCrs );
}
}
else
@@ -293,13 +293,13 @@ void QgsProjectionSelectionWidget::addProjectCrsOption()
{
if ( mProjectCrs.isValid() )
{
mCrsComboBox->addItem( tr( "Project CRS: %1 - %2" ).arg( mProjectCrs.authid(), mProjectCrs.description() ), QgsProjectionSelectionWidget::ProjectCrs );
mCrsComboBox->addItem( tr( "Project CRS: %1" ).arg( mProjectCrs.userFriendlyIdentifier() ), QgsProjectionSelectionWidget::ProjectCrs );
}
}

void QgsProjectionSelectionWidget::addDefaultCrsOption()
{
mCrsComboBox->addItem( tr( "Default CRS: %1 - %2" ).arg( mDefaultCrs.authid(), mDefaultCrs.description() ), QgsProjectionSelectionWidget::DefaultCrs );
mCrsComboBox->addItem( tr( "Default CRS: %1" ).arg( mDefaultCrs.userFriendlyIdentifier() ), QgsProjectionSelectionWidget::DefaultCrs );
}

void QgsProjectionSelectionWidget::addCurrentCrsOption()
@@ -312,7 +312,7 @@ void QgsProjectionSelectionWidget::addCurrentCrsOption()
QString QgsProjectionSelectionWidget::crsOptionText( const QgsCoordinateReferenceSystem &crs )
{
if ( crs.isValid() )
return tr( "%1 - %2" ).arg( crs.authid(), crs.description() );
return crs.userFriendlyIdentifier();
else
return tr( "invalid projection" );
}
@@ -332,7 +332,7 @@ void QgsProjectionSelectionWidget::addRecentCrs()

if ( crs.isValid() )
{
mCrsComboBox->addItem( tr( "%1 - %2" ).arg( crs.authid(), crs.description() ), QgsProjectionSelectionWidget::RecentCrs );
mCrsComboBox->addItem( crs.userFriendlyIdentifier(), QgsProjectionSelectionWidget::RecentCrs );
mCrsComboBox->setItemData( mCrsComboBox->count() - 1, QVariant( ( long long )srsid ), Qt::UserRole + 1 );
}
}

0 comments on commit b5e0692

Please sign in to comment.
You can’t perform that action at this time.