QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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 #include "qgscoordinatetransform.h"
21 #include "qgslogger.h"
22 #include "qgssettings.h"
23 #include "qgsproject.h"
24 
25 #include <QDir>
26 #include <QPushButton>
27 
29  const QgsCoordinateReferenceSystem &destinationCrs,
30  QPair<int, int> selectedDatumTransforms,
31  QWidget *parent,
32  Qt::WindowFlags f )
33  : QDialog( parent, f )
34 {
35  setupUi( this );
36 
37  mDatumTransformTableWidget->setColumnCount( 2 );
38  QStringList headers;
39  headers << tr( "Source transform" ) << tr( "Destination transform" ) ;
40  mDatumTransformTableWidget->setHorizontalHeaderLabels( headers );
41 
42  mSourceProjectionSelectionWidget->setCrs( sourceCrs );
43  mDestinationProjectionSelectionWidget->setCrs( destinationCrs );
44 
45  connect( mHideDeprecatedCheckBox, &QCheckBox::stateChanged, this, &QgsDatumTransformDialog::mHideDeprecatedCheckBox_stateChanged );
46  connect( mDatumTransformTableWidget, &QTableWidget::currentItemChanged, this, &QgsDatumTransformDialog::tableCurrentItemChanged );
47 
48  connect( mSourceProjectionSelectionWidget, &QgsProjectionSelectionWidget::crsChanged, this, &QgsDatumTransformDialog::setSourceCrs );
49  connect( mDestinationProjectionSelectionWidget, &QgsProjectionSelectionWidget::crsChanged, this, &QgsDatumTransformDialog::setDestinationCrs );
50 
51  //get list of datum transforms
52  mSourceCrs = sourceCrs;
53  mDestinationCrs = destinationCrs;
54  mDatumTransforms = QgsDatumTransform::datumTransformations( sourceCrs, destinationCrs );
55 
56  QApplication::setOverrideCursor( Qt::ArrowCursor );
57 
58  setOKButtonEnabled();
59 
60  QgsSettings settings;
61  restoreGeometry( settings.value( QStringLiteral( "Windows/DatumTransformDialog/geometry" ) ).toByteArray() );
62  mHideDeprecatedCheckBox->setChecked( settings.value( QStringLiteral( "Windows/DatumTransformDialog/hideDeprecated" ), false ).toBool() );
63 
64  mLabelSrcDescription->clear();
65  mLabelDstDescription->clear();
66 
67  load( selectedDatumTransforms );
68 }
69 
70 void QgsDatumTransformDialog::load( const QPair<int, int> &selectedDatumTransforms )
71 {
72  mDatumTransformTableWidget->setRowCount( 0 );
73 
74  int row = 0;
75 
76  for ( const QgsDatumTransform::TransformPair &transform : qgis::as_const( mDatumTransforms ) )
77  {
78  bool itemDisabled = false;
79  bool itemHidden = false;
80 
81  if ( transform.sourceTransformId == -1 && transform.destinationTransformId == -1 )
82  continue;
83 
84  for ( int i = 0; i < 2; ++i )
85  {
86  QTableWidgetItem *item = new QTableWidgetItem();
87  int nr = i == 0 ? transform.sourceTransformId : transform.destinationTransformId;
88  item->setData( Qt::UserRole, nr );
89 
90  item->setText( QgsDatumTransform::datumTransformToProj( nr ) );
91 
92  //Describe datums in a tooltip
94  if ( info.datumTransformId == -1 )
95  continue;
96 
97  if ( mHideDeprecatedCheckBox->isChecked() && info.deprecated )
98  {
99  itemHidden = true;
100  }
101 
102  QString toolTipString;
103  if ( gridShiftTransformation( item->text() ) )
104  {
105  toolTipString.append( QStringLiteral( "<p><b>NTv2</b></p>" ) );
106  }
107 
108  if ( info.epsgCode > 0 )
109  toolTipString.append( QStringLiteral( "<p><b>EPSG Transformations Code:</b> %1</p>" ).arg( info.epsgCode ) );
110 
111  toolTipString.append( QStringLiteral( "<p><b>Source CRS:</b> %1</p><p><b>Destination CRS:</b> %2</p>" ).arg( info.sourceCrsDescription, info.destinationCrsDescription ) );
112 
113  if ( !info.remarks.isEmpty() )
114  toolTipString.append( QStringLiteral( "<p><b>Remarks:</b> %1</p>" ).arg( info.remarks ) );
115  if ( !info.scope.isEmpty() )
116  toolTipString.append( QStringLiteral( "<p><b>Scope:</b> %1</p>" ).arg( info.scope ) );
117  if ( info.preferred )
118  toolTipString.append( "<p><b>Preferred transformation</b></p>" );
119  if ( info.deprecated )
120  toolTipString.append( "<p><b>Deprecated transformation</b></p>" );
121 
122  item->setToolTip( toolTipString );
123 
124  if ( gridShiftTransformation( item->text() ) && !testGridShiftFileAvailability( item ) )
125  {
126  itemDisabled = true;
127  }
128 
129  if ( !itemHidden )
130  {
131  if ( itemDisabled )
132  {
133  item->setFlags( Qt::NoItemFlags );
134  }
135  mDatumTransformTableWidget->setRowCount( row + 1 );
136  mDatumTransformTableWidget->setItem( row, i, item );
137  }
138  else
139  {
140  delete item;
141  }
142  }
143 
144  if ( transform.sourceTransformId == selectedDatumTransforms.first &&
145  transform.destinationTransformId == selectedDatumTransforms.second )
146  {
147  mDatumTransformTableWidget->selectRow( row );
148  }
149 
150  row++;
151  }
152 
153  mDatumTransformTableWidget->resizeColumnsToContents();
154 
155  setOKButtonEnabled();
156 }
157 
158 void QgsDatumTransformDialog::setOKButtonEnabled()
159 {
160  int row = mDatumTransformTableWidget->currentRow();
161  mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( mSourceCrs.isValid() && mDestinationCrs.isValid() && row >= 0 );
162 }
163 
165 {
166  QgsSettings settings;
167  settings.setValue( QStringLiteral( "Windows/DatumTransformDialog/geometry" ), saveGeometry() );
168  settings.setValue( QStringLiteral( "Windows/DatumTransformDialog/hideDeprecated" ), mHideDeprecatedCheckBox->isChecked() );
169 
170  for ( int i = 0; i < 2; i++ )
171  {
172  settings.setValue( QStringLiteral( "Windows/DatumTransformDialog/columnWidths/%1" ).arg( i ), mDatumTransformTableWidget->columnWidth( i ) );
173  }
174 
175  QApplication::restoreOverrideCursor();
176 }
177 
179 {
180  return mDatumTransforms.count();
181 }
182 
183 
184 QPair<QPair<QgsCoordinateReferenceSystem, int>, QPair<QgsCoordinateReferenceSystem, int> > QgsDatumTransformDialog::selectedDatumTransforms()
185 {
186  int row = mDatumTransformTableWidget->currentRow();
187  QPair< QPair<QgsCoordinateReferenceSystem, int>, QPair<QgsCoordinateReferenceSystem, int > > sdt;
188  sdt.first.first = mSourceCrs;
189  sdt.second.first = mDestinationCrs;
190 
191  if ( row >= 0 )
192  {
193  QTableWidgetItem *srcItem = mDatumTransformTableWidget->item( row, 0 );
194  sdt.first.second = srcItem ? srcItem->data( Qt::UserRole ).toInt() : -1;
195  QTableWidgetItem *destItem = mDatumTransformTableWidget->item( row, 1 );
196  sdt.second.second = destItem ? destItem->data( Qt::UserRole ).toInt() : -1;
197  }
198  else
199  {
200  sdt.first.second = -1;
201  sdt.second.second = -1;
202  }
203  return sdt;
204 }
205 
206 bool QgsDatumTransformDialog::gridShiftTransformation( const QString &itemText ) const
207 {
208  return !itemText.isEmpty() && !itemText.contains( QLatin1String( "towgs84" ), Qt::CaseInsensitive );
209 }
210 
211 bool QgsDatumTransformDialog::testGridShiftFileAvailability( QTableWidgetItem *item ) const
212 {
213  if ( !item )
214  {
215  return true;
216  }
217 
218  QString itemText = item->text();
219  if ( itemText.isEmpty() )
220  {
221  return true;
222  }
223 
224  char *projLib = getenv( "PROJ_LIB" );
225  if ( !projLib ) //no information about installation directory
226  {
227  return true;
228  }
229 
230  QStringList itemEqualSplit = itemText.split( '=' );
231  QString filename;
232  for ( int i = 1; i < itemEqualSplit.size(); ++i )
233  {
234  if ( i > 1 )
235  {
236  filename.append( '=' );
237  }
238  filename.append( itemEqualSplit.at( i ) );
239  }
240 
241  QDir projDir( projLib );
242  if ( projDir.exists() )
243  {
244  //look if filename in directory
245  QStringList fileList = projDir.entryList();
246  QStringList::const_iterator fileIt = fileList.constBegin();
247  for ( ; fileIt != fileList.constEnd(); ++fileIt )
248  {
249 #if defined(Q_OS_WIN)
250  if ( fileIt->compare( filename, Qt::CaseInsensitive ) == 0 )
251 #else
252  if ( fileIt->compare( filename ) == 0 )
253 #endif //Q_OS_WIN
254  {
255  return true;
256  }
257  }
258  item->setToolTip( tr( "File '%1' not found in directory '%2'" ).arg( filename, projDir.absolutePath() ) );
259  return false; //not found in PROJ_LIB directory
260  }
261  return true;
262 }
263 
264 void QgsDatumTransformDialog::mHideDeprecatedCheckBox_stateChanged( int )
265 {
266  load();
267 }
268 
269 void QgsDatumTransformDialog::tableCurrentItemChanged( QTableWidgetItem *, QTableWidgetItem * )
270 {
271  int row = mDatumTransformTableWidget->currentRow();
272  if ( row < 0 )
273  return;
274 
275  QTableWidgetItem *srcItem = mDatumTransformTableWidget->item( row, 0 );
276  mLabelSrcDescription->setText( srcItem ? srcItem->toolTip() : QString() );
277  QTableWidgetItem *destItem = mDatumTransformTableWidget->item( row, 1 );
278  mLabelDstDescription->setText( destItem ? destItem->toolTip() : QString() );
279 
280  setOKButtonEnabled();
281 }
282 
283 void QgsDatumTransformDialog::setSourceCrs( const QgsCoordinateReferenceSystem &sourceCrs )
284 {
285  mSourceCrs = sourceCrs;
286  mDatumTransforms = QgsDatumTransform::datumTransformations( mSourceCrs, mDestinationCrs );
287  load();
288  setOKButtonEnabled();
289 }
290 
291 void QgsDatumTransformDialog::setDestinationCrs( const QgsCoordinateReferenceSystem &destinationCrs )
292 {
293  mDestinationCrs = destinationCrs;
294  mDatumTransforms = QgsDatumTransform::datumTransformations( mSourceCrs, mDestinationCrs );
295  load();
296  setOKButtonEnabled();
297 }
QString destinationCrsDescription
Destination CRS description.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QPair< QPair< QgsCoordinateReferenceSystem, int >, QPair< QgsCoordinateReferenceSystem, int > > selectedDatumTransforms()
Returns the source and destination transforms, each being a pair of QgsCoordinateReferenceSystems and...
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
int datumTransformId
Datum transform ID.
bool deprecated
True if transform is deprecated.
void saveGeometry(QWidget *widget, const QString &keyName)
Save the wigget geometry into settings.
bool restoreGeometry(QWidget *widget, const QString &keyName)
Restore the wigget geometry from settings.
static QList< QgsDatumTransform::TransformPair > datumTransformations(const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination)
Returns a list of datum transformations which are available for the given source and destination CRS...
QString sourceCrsDescription
Source CRS description.
Contains datum transform information.
bool preferred
True if transform is the preferred transform to use for the source/destination CRS combination...
int epsgCode
EPSG code for the transform, or 0 if not found in EPSG database.
int availableTransformationCount()
Returns the number of possible datum transformation for currently selected source and destination CRS...
QgsDatumTransformDialog(const QgsCoordinateReferenceSystem &sourceCrs=QgsCoordinateReferenceSystem(), const QgsCoordinateReferenceSystem &destinationCrs=QgsCoordinateReferenceSystem(), QPair< int, int > selectedDatumTransforms=qMakePair(-1,-1), QWidget *parent=nullptr, Qt::WindowFlags f=nullptr)
Constructor for QgsDatumTransformDialog.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Contains datum transform information.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
This class represents a coordinate reference system (CRS).
static QString datumTransformToProj(int datumTransformId)
Returns a proj string representing the specified datumTransformId datum transform ID...
QString remarks
Transform remarks.
static QgsDatumTransform::TransformInfo datumTransformInfo(int datumTransformId)
Returns detailed information about the specified datumTransformId.
QString scope
Scope of transform.