QGIS API Documentation  3.14.0-Pi (9f7028fd23)
qgsprojectionselectionwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsprojectionselectionwidget.cpp
3  --------------------------------------
4  Date : 05.01.2015
5  Copyright : (C) 2015 Denis Rouzaud
6  Email : [email protected]
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include <QHBoxLayout>
17 
19 #include "qgsapplication.h"
21 #include "qgsproject.h"
22 #include "qgssettings.h"
24 
26  : QWidget( parent )
27 {
28  QHBoxLayout *layout = new QHBoxLayout();
29  layout->setContentsMargins( 0, 0, 0, 0 );
30  layout->setSpacing( 6 );
31  setLayout( layout );
32 
33  mCrsComboBox = new QgsHighlightableComboBox( this );
34  mCrsComboBox->addItem( tr( "invalid projection" ), QgsProjectionSelectionWidget::CurrentCrs );
35  mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
36 
37  mProjectCrs = QgsProject::instance()->crs();
38  addProjectCrsOption();
39 
40  QgsSettings settings;
41  mDefaultCrs = QgsCoordinateReferenceSystem( settings.value( QStringLiteral( "/projections/defaultProjectCrs" ), geoEpsgCrsAuthId(), QgsSettings::App ).toString() );
42  if ( mDefaultCrs.authid() != mProjectCrs.authid() )
43  {
44  //only show default CRS option if it's different to the project CRS, avoids
45  //needlessly cluttering the widget
46  addDefaultCrsOption();
47  }
48 
49  addRecentCrs();
50 
51  layout->addWidget( mCrsComboBox );
52 
53  mButton = new QToolButton( this );
54  mButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionSetProjection.svg" ) ) );
55  mButton->setToolTip( tr( "Select CRS" ) );
56  layout->addWidget( mButton );
57 
58  setFocusPolicy( Qt::StrongFocus );
59  setFocusProxy( mButton );
60  setAcceptDrops( true );
61 
62  connect( mButton, &QToolButton::clicked, this, &QgsProjectionSelectionWidget::selectCrs );
63  connect( mCrsComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsProjectionSelectionWidget::comboIndexChanged );
64 }
65 
67 {
68  switch ( static_cast< CrsOption >( mCrsComboBox->currentData().toInt() ) )
69  {
71  return mLayerCrs;
73  return mProjectCrs;
75  return mDefaultCrs;
77  return mCrs;
79  {
80  long srsid = mCrsComboBox->currentData( Qt::UserRole + 1 ).toLongLong();
82  return crs;
83  }
86  }
87  return mCrs;
88 }
89 
91 {
92  int optionIndex = mCrsComboBox->findData( option );
93 
94  if ( visible && optionIndex < 0 )
95  {
96  //add missing CRS option
97  switch ( option )
98  {
100  {
101  setLayerCrs( mLayerCrs );
102  return;
103  }
105  {
106  addProjectCrsOption();
107  return;
108  }
110  {
111  addDefaultCrsOption();
112  return;
113  }
115  {
116  addCurrentCrsOption();
117  return;
118  }
120  //recently used CRS option cannot be readded
121  return;
123  {
124  addNotSetOption();
125 
126  if ( optionVisible( CurrentCrs ) && !mCrs.isValid() )
127  {
128  // hide invalid option if not set option is shown
129  setOptionVisible( CurrentCrs, false );
130  }
131 
132  return;
133  }
134  }
135  }
136  else if ( !visible && optionIndex >= 0 )
137  {
138  //remove CRS option
139  mCrsComboBox->removeItem( optionIndex );
140 
141  if ( option == CrsNotSet )
142  {
143  setOptionVisible( CurrentCrs, true );
144  }
145  }
146 }
147 
149 {
150  mNotSetText = text;
151  int optionIndex = mCrsComboBox->findData( CrsNotSet );
152  if ( optionIndex >= 0 )
153  {
154  mCrsComboBox->setItemText( optionIndex, mNotSetText );
155  }
156 }
157 
158 void QgsProjectionSelectionWidget::setMessage( const QString &text )
159 {
160  mMessage = text;
161 }
162 
164 {
165  int optionIndex = mCrsComboBox->findData( option );
166  return optionIndex >= 0;
167 }
168 
170 {
171  //find out crs id of current proj4 string
172  QgsProjectionSelectionDialog dlg( this );
173  if ( !mMessage.isEmpty() )
174  dlg.setMessage( mMessage );
175  dlg.setCrs( mCrs );
176 
177  if ( optionVisible( QgsProjectionSelectionWidget::CrsOption::CrsNotSet ) )
178  {
179  dlg.setShowNoProjection( true );
180  }
181 
182  if ( dlg.exec() )
183  {
184  mCrsComboBox->blockSignals( true );
185  mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ) );
186  mCrsComboBox->blockSignals( false );
188  setCrs( crs );
189  emit crsChanged( crs );
190  }
191  else
192  {
193  QApplication::restoreOverrideCursor();
194  }
195 }
196 
197 void QgsProjectionSelectionWidget::dragEnterEvent( QDragEnterEvent *event )
198 {
199  if ( !( event->possibleActions() & Qt::CopyAction ) )
200  {
201  event->ignore();
202  return;
203  }
204 
205  if ( mapLayerFromMimeData( event->mimeData() ) )
206  {
207  // dragged an acceptable layer, phew
208  event->setDropAction( Qt::CopyAction );
209  event->accept();
210  mCrsComboBox->setHighlighted( true );
211  update();
212  }
213  else
214  {
215  event->ignore();
216  }
217 }
218 
219 void QgsProjectionSelectionWidget::dragLeaveEvent( QDragLeaveEvent *event )
220 {
221  if ( mCrsComboBox->isHighlighted() )
222  {
223  event->accept();
224  mCrsComboBox->setHighlighted( false );
225  update();
226  }
227  else
228  {
229  event->ignore();
230  }
231 }
232 
234 {
235  if ( !( event->possibleActions() & Qt::CopyAction ) )
236  {
237  event->ignore();
238  return;
239  }
240 
241  if ( QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
242  {
243  // dropped a map layer
244  setFocus( Qt::MouseFocusReason );
245  event->setDropAction( Qt::CopyAction );
246  event->accept();
247 
248  if ( layer->crs().isValid() )
249  setCrs( layer->crs() );
250  }
251  else
252  {
253  event->ignore();
254  }
255  mCrsComboBox->setHighlighted( false );
256  update();
257 }
258 
259 void QgsProjectionSelectionWidget::addNotSetOption()
260 {
261  mCrsComboBox->insertItem( 0, mNotSetText, QgsProjectionSelectionWidget::CrsNotSet );
262  if ( !mCrs.isValid() )
263  whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
264 }
265 
266 void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
267 {
268  switch ( static_cast< CrsOption >( mCrsComboBox->itemData( idx ).toInt() ) )
269  {
271  emit crsChanged( mLayerCrs );
272  break;
274  emit crsChanged( mProjectCrs );
275  break;
277  emit crsChanged( mCrs );
278  break;
280  emit crsChanged( mDefaultCrs );
281  break;
283  {
284  long srsid = mCrsComboBox->itemData( idx, Qt::UserRole + 1 ).toLongLong();
286  emit crsChanged( crs );
287  break;
288  }
290  emit cleared();
292  break;
293  }
294  updateTooltip();
295 }
296 
298 {
299  if ( crs.isValid() )
300  {
303  mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
304  crsOptionText( crs ) );
305  mCrsComboBox->blockSignals( true );
306  mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ) );
307  mCrsComboBox->blockSignals( false );
308  }
309  else
310  {
311  int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet );
312  if ( crsNotSetIndex >= 0 )
313  {
314  mCrsComboBox->blockSignals( true );
315  mCrsComboBox->setCurrentIndex( crsNotSetIndex );
316  mCrsComboBox->blockSignals( false );
317  }
318  else
319  {
320  mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
321  crsOptionText( crs ) );
322  }
323  }
324  if ( mCrs != crs )
325  {
326  mCrs = crs;
327  emit crsChanged( crs );
328  }
329  updateTooltip();
330 }
331 
333 {
334  int layerItemIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::LayerCrs );
335  if ( crs.isValid() )
336  {
337  if ( layerItemIndex > -1 )
338  {
339  mCrsComboBox->setItemText( layerItemIndex, tr( "Layer CRS: %1" ).arg( crs.userFriendlyIdentifier() ) );
340  }
341  else
342  {
343  mCrsComboBox->insertItem( firstRecentCrsIndex(), tr( "Layer CRS: %1" ).arg( crs.userFriendlyIdentifier() ), QgsProjectionSelectionWidget::LayerCrs );
344  }
345  }
346  else
347  {
348  if ( layerItemIndex > -1 )
349  {
350  mCrsComboBox->removeItem( layerItemIndex );
351  }
352  }
353  mLayerCrs = crs;
354 }
355 
356 void QgsProjectionSelectionWidget::addProjectCrsOption()
357 {
358  if ( mProjectCrs.isValid() )
359  {
360  mCrsComboBox->addItem( tr( "Project CRS: %1" ).arg( mProjectCrs.userFriendlyIdentifier() ), QgsProjectionSelectionWidget::ProjectCrs );
361  }
362 }
363 
364 void QgsProjectionSelectionWidget::addDefaultCrsOption()
365 {
366  mCrsComboBox->addItem( tr( "Default CRS: %1" ).arg( mDefaultCrs.userFriendlyIdentifier() ), QgsProjectionSelectionWidget::DefaultCrs );
367 }
368 
369 void QgsProjectionSelectionWidget::addCurrentCrsOption()
370 {
371  int index = optionVisible( CrsNotSet ) ? 1 : 0;
372  mCrsComboBox->insertItem( index, crsOptionText( mCrs ), QgsProjectionSelectionWidget::CurrentCrs );
373 
374 }
375 
377 {
378  if ( crs.isValid() )
379  return crs.userFriendlyIdentifier();
380  else
381  return tr( "invalid projection" );
382 }
383 
384 void QgsProjectionSelectionWidget::addRecentCrs()
385 {
386  const QList< QgsCoordinateReferenceSystem> recentProjections = QgsCoordinateReferenceSystem::recentCoordinateReferenceSystems();
387  for ( const QgsCoordinateReferenceSystem &crs : recentProjections )
388  {
389  long srsid = crs.srsid();
390 
391  //check if already shown
392  if ( crsIsShown( srsid ) )
393  {
394  continue;
395  }
396 
397  if ( crs.isValid() )
398  {
400  mCrsComboBox->setItemData( mCrsComboBox->count() - 1, QVariant( ( long long )srsid ), Qt::UserRole + 1 );
401  }
402  }
403 }
404 
405 bool QgsProjectionSelectionWidget::crsIsShown( const long srsid ) const
406 {
407  return srsid == mLayerCrs.srsid() || srsid == mDefaultCrs.srsid() || srsid == mProjectCrs.srsid();
408 }
409 
410 int QgsProjectionSelectionWidget::firstRecentCrsIndex() const
411 {
412  for ( int i = 0; i < mCrsComboBox->count(); ++i )
413  {
414  if ( static_cast< CrsOption >( mCrsComboBox->itemData( i ).toInt() ) == RecentCrs )
415  {
416  return i;
417  }
418  }
419  return -1;
420 }
421 
422 void QgsProjectionSelectionWidget::updateTooltip()
423 {
425  if ( c.isValid() )
426  setToolTip( c.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED, true ) );
427  else
428  setToolTip( QString() );
429 }
430 
431 QgsMapLayer *QgsProjectionSelectionWidget::mapLayerFromMimeData( const QMimeData *data ) const
432 {
434  for ( const QgsMimeDataUtils::Uri &u : uriList )
435  {
436  // is this uri from the current project?
437  if ( QgsMapLayer *layer = u.mapLayer() )
438  {
439  return layer;
440  }
441  }
442  return nullptr;
443 }
QgsProjectionSelectionWidget::crs
QgsCoordinateReferenceSystem crs() const
Returns the currently selected CRS for the widget.
Definition: qgsprojectionselectionwidget.cpp:66
qgsprojectionselectionwidget.h
QgsProjectionSelectionWidget::selectCrs
void selectCrs()
Opens the dialog for selecting a new CRS.
Definition: qgsprojectionselectionwidget.cpp:169
QgsApplication::getThemeIcon
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
Definition: qgsapplication.cpp:605
QgsSettings::value
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Definition: qgssettings.cpp:174
QgsProjectionSelectionWidget::setMessage
void setMessage(const QString &text)
Sets a message to show in the dialog.
Definition: qgsprojectionselectionwidget.cpp:158
qgshighlightablecombobox.h
QgsCoordinateReferenceSystem::userFriendlyIdentifier
QString userFriendlyIdentifier(IdentifierType type=MediumString) const
Returns a user friendly identifier for the CRS.
Definition: qgscoordinatereferencesystem.cpp:1316
QgsSettings::App
@ App
Definition: qgssettings.h:75
QgsCoordinateReferenceSystem::WKT_PREFERRED
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition: qgscoordinatereferencesystem.h:678
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsHighlightableComboBox::isHighlighted
bool isHighlighted() const
Returns true if the combo box is currently highlighted.
Definition: qgshighlightablecombobox.h:48
QgsProjectionSelectionWidget::crsChanged
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
QgsProjectionSelectionDialog
Definition: qgsprojectionselectiondialog.h:51
QgsProjectionSelectionDialog::setShowNoProjection
void setShowNoProjection(bool show)
Sets whether a "no/invalid" projection option should be shown.
Definition: qgsprojectionselectiondialog.cpp:61
QgsProjectionSelectionWidget::cleared
void cleared()
Emitted when the not set option is selected.
QgsProjectionSelectionDialog::crs
QgsCoordinateReferenceSystem crs() const
Returns the CRS currently selected in the widget.
Definition: qgsprojectionselectiondialog.cpp:71
QgsProjectionSelectionDialog::setMessage
void setMessage(const QString &message)
Sets a message to show in the dialog.
Definition: qgsprojectionselectiondialog.cpp:41
geoEpsgCrsAuthId
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
Definition: qgis.h:666
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:458
QgsProjectionSelectionDialog::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the initial crs to show within the dialog.
Definition: qgsprojectionselectiondialog.cpp:76
QgsSettings
Definition: qgssettings.h:61
QgsProjectionSelectionWidget::optionVisible
bool optionVisible(CrsOption option) const
Returns whether the specified CRS option is visible in the widget.
Definition: qgsprojectionselectionwidget.cpp:163
QgsMimeDataUtils::UriList
QList< QgsMimeDataUtils::Uri > UriList
Definition: qgsmimedatautils.h:156
QgsProjectionSelectionWidget::dropEvent
void dropEvent(QDropEvent *event) override
Definition: qgsprojectionselectionwidget.cpp:233
QgsProjectionSelectionWidget::setLayerCrs
void setLayerCrs(const QgsCoordinateReferenceSystem &crs)
Sets the layer CRS for the widget.
Definition: qgsprojectionselectionwidget.cpp:332
qgsapplication.h
qgsprojectionselectiondialog.h
QgsProjectionSelectionWidget::setOptionVisible
void setOptionVisible(CrsOption option, bool visible)
Sets whether a predefined CRS option should be shown in the widget.
Definition: qgsprojectionselectionwidget.cpp:90
QgsCoordinateReferenceSystem::fromSrsId
static QgsCoordinateReferenceSystem fromSrsId(long srsId)
Creates a CRS from a specified QGIS SRS ID.
Definition: qgscoordinatereferencesystem.cpp:240
QgsCoordinateReferenceSystem::srsid
long srsid() const
Returns the internal CRS ID, if available.
Definition: qgscoordinatereferencesystem.cpp:1289
whileBlocking
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:262
QgsProjectionSelectionWidget::ProjectCrs
@ ProjectCrs
Current project CRS (if OTF reprojection enabled)
Definition: qgsprojectionselectionwidget.h:49
QgsCoordinateReferenceSystem::authid
QString authid() const
Returns the authority identifier for the CRS.
Definition: qgscoordinatereferencesystem.cpp:1299
QgsHighlightableComboBox
Definition: qgshighlightablecombobox.h:34
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:902
QgsProjectionSelectionWidget::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the current CRS for the widget.
Definition: qgsprojectionselectionwidget.cpp:297
QgsProjectionSelectionWidget::RecentCrs
@ RecentCrs
Recently used CRS.
Definition: qgsprojectionselectionwidget.h:52
QgsMimeDataUtils::Uri
Definition: qgsmimedatautils.h:40
QgsProjectionSelectionWidget::CrsNotSet
@ CrsNotSet
Not set (hidden by default)
Definition: qgsprojectionselectionwidget.h:53
QgsCoordinateReferenceSystem
Definition: qgscoordinatereferencesystem.h:206
QgsProjectionSelectionWidget::LayerCrs
@ LayerCrs
Optional layer CRS.
Definition: qgsprojectionselectionwidget.h:48
QgsProjectionSelectionWidget::setNotSetText
void setNotSetText(const QString &text)
Sets the text to show for the not set option.
Definition: qgsprojectionselectionwidget.cpp:148
QgsMimeDataUtils::decodeUriList
static UriList decodeUriList(const QMimeData *data)
Definition: qgsmimedatautils.cpp:210
QgsProjectionSelectionWidget::DefaultCrs
@ DefaultCrs
Global default QGIS CRS.
Definition: qgsprojectionselectionwidget.h:51
c
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
Definition: porting_processing.dox:1
QgsMapLayer
Definition: qgsmaplayer.h:81
QgsProjectionSelectionWidget::crsOptionText
static QString crsOptionText(const QgsCoordinateReferenceSystem &crs)
Returns display text for the specified crs.
Definition: qgsprojectionselectionwidget.cpp:376
qgssettings.h
QgsProjectionSelectionWidget::dragLeaveEvent
void dragLeaveEvent(QDragLeaveEvent *event) override
Definition: qgsprojectionselectionwidget.cpp:219
QgsProjectionSelectionWidget::CrsOption
CrsOption
Predefined CRS options shown in widget.
Definition: qgsprojectionselectionwidget.h:46
QgsProject::crs
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:98
QgsHighlightableComboBox::setHighlighted
void setHighlighted(bool highlighted)
Sets whether the combo box is currently highlighted.
Definition: qgshighlightablecombobox.cpp:36
qgsproject.h
QgsProjectionSelectionWidget::QgsProjectionSelectionWidget
QgsProjectionSelectionWidget(QWidget *parent=nullptr)
Constructor for QgsProjectionSelectionWidget.
Definition: qgsprojectionselectionwidget.cpp:25
QgsProjectionSelectionWidget::CurrentCrs
@ CurrentCrs
Current user selected CRS.
Definition: qgsprojectionselectionwidget.h:50
QgsProjectionSelectionWidget::dragEnterEvent
void dragEnterEvent(QDragEnterEvent *event) override
Definition: qgsprojectionselectionwidget.cpp:197
QgsCoordinateReferenceSystem::recentCoordinateReferenceSystems
static QList< QgsCoordinateReferenceSystem > recentCoordinateReferenceSystems()
Returns a list of recently used CRS.
Definition: qgscoordinatereferencesystem.cpp:3565