Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Show nice friendly warnings to users when
- A coordinate transform cannot be created, e.g. due to not making sense (transforming earth coords to mars coords) - A coordinate transform cannot be created due to a missing grid file (along with links to download the grid if available) - A coordinate transform was created, BUT a better one is possible, it just is missing some prerequisite on the user's system (again, with links to download if available) Sponsored by ICSM
- Loading branch information
1 parent
a8b5583
commit 3e89df8
Showing
5 changed files
with
280 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,203 @@ | ||
/*************************************************************************** | ||
qgsappcoordinateoperationhandlers.cpp | ||
------------------------- | ||
begin : May 2019 | ||
copyright : (C) 2019 by Nyall Dawson | ||
email : nyall dot dawson at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
#include "qgsappcoordinateoperationhandlers.h" | ||
#include "qgscoordinatetransform.h" | ||
#include "qgisapp.h" | ||
#include "qgsmessagebar.h" | ||
#include "qgsmessagebaritem.h" | ||
#include "qgsmessageoutput.h" | ||
|
||
// | ||
// QgsAppMissingRequiredGridHandler | ||
// | ||
QgsAppMissingGridHandler::QgsAppMissingGridHandler( QObject *parent ) | ||
: QObject( parent ) | ||
{ | ||
QgsCoordinateTransform::setCustomMissingRequiredGridHandler( [ = ]( const QgsCoordinateReferenceSystem & sourceCrs, | ||
const QgsCoordinateReferenceSystem & destinationCrs, | ||
const QgsDatumTransform::GridDetails & grid ) | ||
{ | ||
emit missingRequiredGrid( sourceCrs, destinationCrs, grid ); | ||
} ); | ||
|
||
QgsCoordinateTransform::setCustomMissingPreferredGridHandler( [ = ]( const QgsCoordinateReferenceSystem & sourceCrs, | ||
const QgsCoordinateReferenceSystem & destinationCrs, | ||
const QgsDatumTransform::TransformDetails & preferredOperation, | ||
const QgsDatumTransform::TransformDetails & availableOperation ) | ||
{ | ||
emit missingPreferredGrid( sourceCrs, destinationCrs, preferredOperation, availableOperation ); | ||
} ); | ||
|
||
QgsCoordinateTransform::setCustomCoordinateOperationCreationErrorHandler( [ = ]( const QgsCoordinateReferenceSystem & sourceCrs, | ||
const QgsCoordinateReferenceSystem & destinationCrs, | ||
const QString & error ) | ||
{ | ||
emit coordinateOperationCreationError( sourceCrs, destinationCrs, error ); | ||
} ); | ||
|
||
connect( this, &QgsAppMissingGridHandler::missingRequiredGrid, this, &QgsAppMissingGridHandler::onMissingRequiredGrid, Qt::QueuedConnection ); | ||
connect( this, &QgsAppMissingGridHandler::missingPreferredGrid, this, &QgsAppMissingGridHandler::onMissingPreferredGrid, Qt::QueuedConnection ); | ||
connect( this, &QgsAppMissingGridHandler::coordinateOperationCreationError, this, &QgsAppMissingGridHandler::onCoordinateOperationCreationError, Qt::QueuedConnection ); | ||
|
||
} | ||
|
||
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.toProj4().isEmpty() ) | ||
return crs.toProj4(); | ||
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 ) ); | ||
|
||
QString downloadMessage; | ||
if ( !grid.url.isEmpty() ) | ||
{ | ||
if ( !grid.packageName.isEmpty() ) | ||
{ | ||
downloadMessage = 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 ); | ||
} | ||
else | ||
{ | ||
downloadMessage = tr( "This grid is available for download from <a href=\"%1\">%1</a>." ).arg( grid.url ); | ||
} | ||
} | ||
|
||
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.%4</p>" ).arg( displayIdentifierForCrs( sourceCrs ), | ||
displayIdentifierForCrs( destinationCrs ), | ||
grid.shortName, | ||
downloadMessage.isEmpty() ? QString() : " " + downloadMessage ); | ||
|
||
QgsMessageBar *bar = QgisApp::instance()->messageBar(); | ||
QgsMessageBarItem *widget = bar->createMessage( QString(), shortMessage ); | ||
QPushButton *detailsButton = new QPushButton( tr( "Details" ) ); | ||
connect( detailsButton, &QPushButton::clicked, this, [longMessage] | ||
{ | ||
// dlg has deleted on close | ||
QgsMessageOutput * dlg( QgsMessageOutput::createMessageOutput() ); | ||
dlg->setTitle( tr( "No Transformations Available" ) ); | ||
dlg->setMessage( longMessage, QgsMessageOutput::MessageHtml ); | ||
dlg->showMessage(); | ||
} ); | ||
|
||
widget->layout()->addWidget( detailsButton ); | ||
bar->pushWidget( widget, Qgis::Critical, 0 ); | ||
} | ||
|
||
void QgsAppMissingGridHandler::onMissingPreferredGrid( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QgsDatumTransform::TransformDetails &preferredOperation, const QgsDatumTransform::TransformDetails &availableOperation ) | ||
{ | ||
if ( !shouldWarnAboutPair( sourceCrs, destinationCrs ) ) | ||
return; | ||
|
||
const QString shortMessage = tr( "Cannot use preferred transform between %1 and %2" ).arg( displayIdentifierForCrs( sourceCrs, true ), | ||
displayIdentifierForCrs( destinationCrs, true ) ); | ||
|
||
QString gridMessage; | ||
for ( const QgsDatumTransform::GridDetails &grid : preferredOperation.grids ) | ||
{ | ||
if ( !grid.isAvailable ) | ||
{ | ||
QString m = tr( "This transformation requires the grid file “%1”, which is not available for use on the system." ).arg( grid.shortName ); | ||
if ( !grid.url.isEmpty() ) | ||
{ | ||
if ( !grid.packageName.isEmpty() ) | ||
{ | ||
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 ); | ||
} | ||
else | ||
{ | ||
m += ' ' + tr( "This grid is available for download from <a href=\"%1\">%1</a>." ).arg( grid.url ); | ||
} | ||
} | ||
gridMessage += QStringLiteral( "<li>%1</li>" ).arg( m ); | ||
} | ||
} | ||
if ( !gridMessage.isEmpty() ) | ||
{ | ||
gridMessage = "<ul>" + gridMessage + "</ul>"; | ||
} | ||
|
||
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 ) ) | ||
+ gridMessage + | ||
tr( "<p>Current transform “<i>%1</i>” has an accuracy of %2 meters, while the preferred transformation “<i>%3</i>” has accuracy %4 meters.</p>" ).arg( availableOperation.name ) | ||
.arg( availableOperation.accuracy ).arg( preferredOperation.name ).arg( preferredOperation.accuracy ); | ||
|
||
QgsMessageBar *bar = QgisApp::instance()->messageBar(); | ||
QgsMessageBarItem *widget = bar->createMessage( QString(), shortMessage ); | ||
QPushButton *detailsButton = new QPushButton( tr( "Details" ) ); | ||
connect( detailsButton, &QPushButton::clicked, this, [longMessage] | ||
{ | ||
// dlg has deleted on close | ||
QgsMessageOutput * dlg( QgsMessageOutput::createMessageOutput() ); | ||
dlg->setTitle( tr( "Preferred Transformation Not Available" ) ); | ||
dlg->setMessage( longMessage, QgsMessageOutput::MessageHtml ); | ||
dlg->showMessage(); | ||
} ); | ||
|
||
widget->layout()->addWidget( detailsButton ); | ||
bar->pushWidget( widget, Qgis::Warning, 0 ); | ||
} | ||
|
||
void QgsAppMissingGridHandler::onCoordinateOperationCreationError( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QString &error ) | ||
{ | ||
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 longMessage = tr( "<p>No transform is available between <i>%1</i> and <i>%2</i>.</p><p>%3</p>" ).arg( displayIdentifierForCrs( sourceCrs ), displayIdentifierForCrs( destinationCrs ), error ); | ||
|
||
QgsMessageBar *bar = QgisApp::instance()->messageBar(); | ||
QgsMessageBarItem *widget = bar->createMessage( QString(), shortMessage ); | ||
QPushButton *detailsButton = new QPushButton( tr( "Details" ) ); | ||
connect( detailsButton, &QPushButton::clicked, this, [longMessage] | ||
{ | ||
// dlg has deleted on close | ||
QgsMessageOutput * dlg( QgsMessageOutput::createMessageOutput() ); | ||
dlg->setTitle( tr( "No Transformations Available" ) ); | ||
dlg->setMessage( longMessage, QgsMessageOutput::MessageHtml ); | ||
dlg->showMessage(); | ||
} ); | ||
|
||
widget->layout()->addWidget( detailsButton ); | ||
bar->pushWidget( widget, Qgis::Critical, 0 ); | ||
} | ||
|
||
bool QgsAppMissingGridHandler::shouldWarnAboutPair( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &dest ) | ||
{ | ||
if ( mAlreadyWarnedPairs.contains( qMakePair( source, dest ) ) || mAlreadyWarnedPairs.contains( qMakePair( dest, source ) ) ) | ||
{ | ||
return false; | ||
} | ||
|
||
mAlreadyWarnedPairs.append( qMakePair( source, dest ) ); | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/*************************************************************************** | ||
qgsappcoordinateoperationhandlers.h | ||
------------------------- | ||
begin : May 2019 | ||
copyright : (C) 2019 by Nyall Dawson | ||
email : nyall dot dawson at gmail dot com | ||
*************************************************************************** | ||
* * | ||
* This program is free software; you can redistribute it and/or modify * | ||
* it under the terms of the GNU General Public License as published by * | ||
* the Free Software Foundation; either version 2 of the License, or * | ||
* (at your option) any later version. * | ||
* * | ||
***************************************************************************/ | ||
#ifndef QGSAPPCOORDINATEOPERATIONHANDLERS_H | ||
#define QGSAPPCOORDINATEOPERATIONHANDLERS_H | ||
|
||
#include <QObject> | ||
#include "qgscoordinatereferencesystem.h" | ||
#include "qgsdatumtransform.h" | ||
|
||
/** | ||
* Alerts users when a transform grids are required (or desired) for an operation between two | ||
* CRSes, yet they are not available on the current system. | ||
*/ | ||
class QgsAppMissingGridHandler : public QObject | ||
{ | ||
Q_OBJECT | ||
public: | ||
|
||
QgsAppMissingGridHandler( QObject *parent ); | ||
|
||
signals: | ||
|
||
void missingRequiredGrid( const QgsCoordinateReferenceSystem &sourceCrs, | ||
const QgsCoordinateReferenceSystem &destinationCrs, | ||
const QgsDatumTransform::GridDetails &grid ); | ||
|
||
void missingPreferredGrid( const QgsCoordinateReferenceSystem &sourceCrs, | ||
const QgsCoordinateReferenceSystem &destinationCrs, | ||
const QgsDatumTransform::TransformDetails &preferredOperation, | ||
const QgsDatumTransform::TransformDetails &availableOperation ); | ||
|
||
void coordinateOperationCreationError( const QgsCoordinateReferenceSystem &sourceCrs, | ||
const QgsCoordinateReferenceSystem &destinationCrs, | ||
const QString &error ); | ||
|
||
private slots: | ||
|
||
void onMissingRequiredGrid( const QgsCoordinateReferenceSystem &sourceCrs, | ||
const QgsCoordinateReferenceSystem &destinationCrs, | ||
const QgsDatumTransform::GridDetails &grid ); | ||
|
||
void onMissingPreferredGrid( const QgsCoordinateReferenceSystem &sourceCrs, | ||
const QgsCoordinateReferenceSystem &destinationCrs, | ||
const QgsDatumTransform::TransformDetails &preferredOperation, | ||
const QgsDatumTransform::TransformDetails &availableOperation ); | ||
|
||
void onCoordinateOperationCreationError( const QgsCoordinateReferenceSystem &sourceCrs, | ||
const QgsCoordinateReferenceSystem &destinationCrs, | ||
const QString &error ); | ||
private: | ||
|
||
bool shouldWarnAboutPair( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &dest ); | ||
|
||
QList< QPair< QgsCoordinateReferenceSystem, QgsCoordinateReferenceSystem > > mAlreadyWarnedPairs; | ||
|
||
}; | ||
|
||
#endif // QGSAPPCOORDINATEOPERATIONHANDLERS_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters