QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsdatumtransformdialog.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsdatumtransformdialog.cpp
3 ---------------------------
4 begin : November 2013
5 copyright : (C) 2013 by Marco Hugentobler
6 email : marco.hugentobler at sourcepole dot ch
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include <proj.h>
21
23#include "qgsgui.h"
24#include "qgsguiutils.h"
25#include "qgshelp.h"
26#include "qgslogger.h"
27#include "qgsproject.h"
29#include "qgsprojutils.h"
30#include "qgssettings.h"
31
32#include <QDir>
33#include <QPushButton>
34#include <QString>
35
36#include "moc_qgsdatumtransformdialog.cpp"
37
38using namespace Qt::StringLiterals;
39
40bool QgsDatumTransformDialog::run( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, QWidget *parent, QgsMapCanvas *mapCanvas, const QString &windowTitle )
41{
42 if ( sourceCrs == destinationCrs )
43 return true;
44
46 if ( context.hasTransform( sourceCrs, destinationCrs ) )
47 {
48 return true;
49 }
50
51 QgsDatumTransformDialog dlg( sourceCrs, destinationCrs, false, true, false, qMakePair( -1, -1 ), parent, Qt::WindowFlags(), QString(), mapCanvas );
52 if ( !windowTitle.isEmpty() )
53 dlg.setWindowTitle( windowTitle );
54
55 if ( dlg.shouldAskUserForSelection() )
56 {
57 if ( dlg.exec() )
58 {
66 return true;
67 }
68 else
69 {
70 return false;
71 }
72 }
73 else
74 {
75 dlg.applyDefaultTransform();
76 return true;
77 }
78}
79
83 const bool allowCrsChanges,
84 const bool showMakeDefault,
85 const bool forceChoice,
86 QPair<int, int> selectedDatumTransforms,
87 QWidget *parent,
88 Qt::WindowFlags f,
89 const QString &selectedProj,
90 QgsMapCanvas *mapCanvas,
91 bool allowFallback
92)
93 : QDialog( parent, f )
94 , mPreviousCursorOverride( std::make_unique<QgsTemporaryCursorRestoreOverride>() ) // this dialog is often shown while cursor overrides are in place, so temporarily remove them
95{
96 setupUi( this );
97
98 QgsCoordinateReferenceSystem sourceCrs = sCrs;
99 QgsCoordinateReferenceSystem destinationCrs = dCrs;
100
102
103 if ( !showMakeDefault )
104 mCoordinateOperationsWidget->setShowMakeDefault( false );
105
106 if ( forceChoice )
107 {
108 mButtonBox->removeButton( mButtonBox->button( QDialogButtonBox::Cancel ) );
109 setWindowFlags( windowFlags() | Qt::CustomizeWindowHint );
110 setWindowFlags( windowFlags() & ~Qt::WindowCloseButtonHint );
111 }
112
113 if ( !sourceCrs.isValid() )
114 sourceCrs = QgsProject::instance()->crs();
115 if ( !sourceCrs.isValid() )
116 sourceCrs = QgsCoordinateReferenceSystem( u"EPSG:4326"_s );
117 if ( !destinationCrs.isValid() )
118 destinationCrs = QgsProject::instance()->crs();
119 if ( !destinationCrs.isValid() )
120 destinationCrs = QgsCoordinateReferenceSystem( u"EPSG:4326"_s );
121
122 mSourceProjectionSelectionWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, false );
123 mDestinationProjectionSelectionWidget->setOptionVisible( QgsProjectionSelectionWidget::CrsNotSet, false );
124
125 mSourceProjectionSelectionWidget->setCrs( sourceCrs );
126 mDestinationProjectionSelectionWidget->setCrs( destinationCrs );
127 if ( !allowCrsChanges )
128 {
129 mCrsStackedWidget->setCurrentIndex( 1 );
130 mSourceProjectionSelectionWidget->setEnabled( false );
131 mDestinationProjectionSelectionWidget->setEnabled( false );
132 mSourceCrsLabel->setText( QgsProjectionSelectionWidget::crsOptionText( sourceCrs ) );
133 mDestCrsLabel->setText( QgsProjectionSelectionWidget::crsOptionText( destinationCrs ) );
134 }
135
136 mCoordinateOperationsWidget->setMapCanvas( mapCanvas );
137
138 connect( mSourceProjectionSelectionWidget, &QgsProjectionSelectionWidget::crsChanged, this, &QgsDatumTransformDialog::setSourceCrs );
139 connect( mDestinationProjectionSelectionWidget, &QgsProjectionSelectionWidget::crsChanged, this, &QgsDatumTransformDialog::setDestinationCrs );
140
141 mCoordinateOperationsWidget->setSourceCrs( sourceCrs );
142 mCoordinateOperationsWidget->setDestinationCrs( destinationCrs );
143
144 connect( mButtonBox, &QDialogButtonBox::helpRequested, this, [] { QgsHelp::openHelp( u"working_with_projections/working_with_projections.html"_s ); } );
145
146 connect( mCoordinateOperationsWidget, &QgsCoordinateOperationWidget::operationChanged, this, &QgsDatumTransformDialog::operationChanged );
148 deets.proj = selectedProj;
149 deets.sourceTransformId = selectedDatumTransforms.first;
150 deets.destinationTransformId = selectedDatumTransforms.second;
151 deets.allowFallback = allowFallback;
152 mCoordinateOperationsWidget->setSelectedOperation( deets );
153
154 connect( mCoordinateOperationsWidget, &QgsCoordinateOperationWidget::operationDoubleClicked, this, [this] {
155 if ( mCoordinateOperationsWidget->sourceCrs().isValid() && mCoordinateOperationsWidget->destinationCrs().isValid() && mCoordinateOperationsWidget->selectedOperation().isAvailable )
156 accept();
157 } );
158}
159
160void QgsDatumTransformDialog::setOKButtonEnabled()
161{
162 mButtonBox->button( QDialogButtonBox::Ok )
163 ->setEnabled( mCoordinateOperationsWidget->sourceCrs().isValid() && mCoordinateOperationsWidget->destinationCrs().isValid() && mCoordinateOperationsWidget->selectedOperation().isAvailable );
164}
165
167{
168 if ( mCoordinateOperationsWidget->makeDefaultSelected() && mCoordinateOperationsWidget->hasSelection() )
169 {
170 QgsSettings settings;
171 settings.beginGroup( u"/Projections"_s );
172
174
175 const QString srcAuthId = dt.sourceCrs.authid();
176 const QString destAuthId = dt.destinationCrs.authid();
177 const int sourceDatumTransform = dt.sourceTransformId;
178 QString sourceDatumProj;
180 if ( sourceDatumTransform >= 0 )
181 sourceDatumProj = QgsDatumTransform::datumTransformToProj( sourceDatumTransform );
182 const int destinationDatumTransform = dt.destinationTransformId;
183 QString destinationDatumProj;
184 if ( destinationDatumTransform >= 0 )
185 destinationDatumProj = QgsDatumTransform::datumTransformToProj( destinationDatumTransform );
187 settings.setValue( srcAuthId + u"//"_s + destAuthId + u"_srcTransform"_s, sourceDatumProj );
188 settings.setValue( srcAuthId + u"//"_s + destAuthId + u"_destTransform"_s, destinationDatumProj );
189 settings.setValue( srcAuthId + u"//"_s + destAuthId + u"_coordinateOp"_s, dt.proj );
190 settings.setValue( srcAuthId + u"//"_s + destAuthId + u"_allowFallback"_s, dt.allowFallback );
191 }
192 QDialog::accept();
193}
194
196{
197 if ( !mButtonBox->button( QDialogButtonBox::Cancel ) )
198 return; // users HAVE to make a choice, no click on the dialog "x" to avoid this!
199
200 QDialog::reject();
201}
202
203bool QgsDatumTransformDialog::shouldAskUserForSelection() const
204{
205 if ( mCoordinateOperationsWidget->availableOperations().count() > 1 )
206 {
207 return QgsSettings().value( u"/projections/promptWhenMultipleTransformsExist"_s, false, QgsSettings::App ).toBool();
208 }
209 // TODO: show if transform grids are required, but missing
210 return false;
211}
212
213QgsDatumTransformDialog::TransformInfo QgsDatumTransformDialog::defaultDatumTransform() const
214{
215 TransformInfo preferred;
216 preferred.sourceCrs = mCoordinateOperationsWidget->sourceCrs();
217 preferred.destinationCrs = mCoordinateOperationsWidget->destinationCrs();
218 const QgsCoordinateOperationWidget::OperationDetails defaultOp = mCoordinateOperationsWidget->defaultOperation();
219 preferred.sourceTransformId = defaultOp.sourceTransformId;
220 preferred.destinationTransformId = defaultOp.destinationTransformId;
221 preferred.proj = defaultOp.proj;
222 return preferred;
223}
224
225void QgsDatumTransformDialog::applyDefaultTransform()
226{
227 if ( mCoordinateOperationsWidget->availableOperations().count() > 0 )
228 {
229 QgsCoordinateTransformContext context = QgsProject::instance()->transformContext();
230 const TransformInfo dt = defaultDatumTransform();
232 context.addSourceDestinationDatumTransform( dt.sourceCrs, dt.destinationCrs, dt.sourceTransformId, dt.destinationTransformId );
234
235 // on proj 6 builds, removing a coordinate operation falls back to default
236 context.removeCoordinateOperation( dt.sourceCrs, dt.destinationCrs );
238 }
239}
240
242{
243 const QgsCoordinateOperationWidget::OperationDetails selected = mCoordinateOperationsWidget->selectedOperation();
244 TransformInfo sdt;
245 sdt.sourceCrs = mCoordinateOperationsWidget->sourceCrs();
246 sdt.destinationCrs = mCoordinateOperationsWidget->destinationCrs();
249 sdt.proj = selected.proj;
250 sdt.allowFallback = selected.allowFallback;
251 return sdt;
252}
253
254bool QgsDatumTransformDialog::gridShiftTransformation( const QString &itemText ) const
255{
256 return !itemText.isEmpty() && !itemText.contains( "towgs84"_L1, Qt::CaseInsensitive );
257}
258
259void QgsDatumTransformDialog::operationChanged()
260{
261 setOKButtonEnabled();
262}
263
264void QgsDatumTransformDialog::setSourceCrs( const QgsCoordinateReferenceSystem &sourceCrs )
265{
266 mCoordinateOperationsWidget->setSourceCrs( sourceCrs );
267 setOKButtonEnabled();
268}
269
270void QgsDatumTransformDialog::setDestinationCrs( const QgsCoordinateReferenceSystem &destinationCrs )
271{
272 mCoordinateOperationsWidget->setDestinationCrs( destinationCrs );
273 setOKButtonEnabled();
274}
void operationChanged()
Emitted when the operation selected in the dialog is changed.
void operationDoubleClicked()
Emitted when an operation is double-clicked in the widget.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
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...
bool addCoordinateOperation(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QString &coordinateOperationProjString, bool allowFallback=true)
Adds a new coordinateOperationProjString to use when projecting coordinates from the specified source...
void removeCoordinateOperation(const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs)
Removes the coordinate operation for the specified sourceCrs and destinationCrs.
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...
QgsDatumTransformDialog(const QgsCoordinateReferenceSystem &sourceCrs=QgsCoordinateReferenceSystem(), const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem(), bool allowCrsChanges=false, bool showMakeDefault=true, bool forceChoice=true, QPair< int, int > selectedDatumTransforms=qMakePair(-1, -1), QWidget *parent=nullptr, Qt::WindowFlags f=Qt::WindowFlags(), const QString &selectedProj=QString(), QgsMapCanvas *mapCanvas=nullptr, bool allowFallback=true)
Constructor for QgsDatumTransformDialog.
TransformInfo selectedDatumTransform()
Returns the source and destination transforms, each being a pair of QgsCoordinateReferenceSystems and...
static bool run(const QgsCoordinateReferenceSystem &sourceCrs=QgsCoordinateReferenceSystem(), const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem(), QWidget *parent=nullptr, QgsMapCanvas *mapCanvas=nullptr, const QString &windowTitle=QString())
Runs the dialog (if required) prompting for the desired transform to use from sourceCrs to destinatio...
static Q_DECL_DEPRECATED QString datumTransformToProj(int datumTransformId)
Returns a proj string representing the specified datumTransformId datum transform ID.
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...
Definition qgsgui.cpp:224
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition qgshelp.cpp:41
Map canvas is a class for displaying all GIS data types on a canvas.
static QgsProject * instance()
Returns the QgsProject singleton instance.
QgsCoordinateTransformContext transformContext
Definition qgsproject.h:120
QgsCoordinateReferenceSystem crs
Definition qgsproject.h:119
void setTransformContext(const QgsCoordinateTransformContext &context)
Sets the project's coordinate transform context, which stores various information regarding which dat...
@ CrsNotSet
Not set (hidden by default).
static QString crsOptionText(const QgsCoordinateReferenceSystem &crs)
Returns display text for the specified crs.
void crsChanged(const QgsCoordinateReferenceSystem &crs)
Emitted when the selected CRS is changed.
Stores settings for use within QGIS.
Definition qgssettings.h:68
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void beginGroup(const QString &prefix, QgsSettings::Section section=QgsSettings::NoSection)
Appends prefix to the current group.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
Temporarily removes all cursor overrides for the QApplication for the lifetime of the object.
#define Q_NOWARN_DEPRECATED_POP
Definition qgis.h:7504
#define Q_NOWARN_DEPRECATED_PUSH
Definition qgis.h:7503
bool allowFallback
true if fallback transforms can be used
QString proj
Proj coordinate operation description, for Proj >= 6.0 builds only.
Dialog transformation entry info.
int destinationTransformId
Destination transform ID.
QString proj
Proj coordinate operation description, for Proj >= 6.0 builds only.
QgsCoordinateReferenceSystem sourceCrs
Source coordinate reference system.
QgsCoordinateReferenceSystem destinationCrs
Destination coordinate reference system.
bool allowFallback
true if fallback transforms can be used