QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
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 ( !mNotSetText.isEmpty() )
178  dlg.setNotSetText( mNotSetText );
179 
180  if ( optionVisible( QgsProjectionSelectionWidget::CrsOption::CrsNotSet ) )
181  {
182  dlg.setShowNoProjection( true );
183  }
184 
185  if ( dlg.exec() )
186  {
187  mCrsComboBox->blockSignals( true );
188  mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ) );
189  mCrsComboBox->blockSignals( false );
191  setCrs( crs );
192  emit crsChanged( crs );
193  }
194  else
195  {
196  QApplication::restoreOverrideCursor();
197  }
198 }
199 
200 void QgsProjectionSelectionWidget::dragEnterEvent( QDragEnterEvent *event )
201 {
202  if ( !( event->possibleActions() & Qt::CopyAction ) )
203  {
204  event->ignore();
205  return;
206  }
207 
208  if ( mapLayerFromMimeData( event->mimeData() ) )
209  {
210  // dragged an acceptable layer, phew
211  event->setDropAction( Qt::CopyAction );
212  event->accept();
213  mCrsComboBox->setHighlighted( true );
214  update();
215  }
216  else
217  {
218  event->ignore();
219  }
220 }
221 
222 void QgsProjectionSelectionWidget::dragLeaveEvent( QDragLeaveEvent *event )
223 {
224  if ( mCrsComboBox->isHighlighted() )
225  {
226  event->accept();
227  mCrsComboBox->setHighlighted( false );
228  update();
229  }
230  else
231  {
232  event->ignore();
233  }
234 }
235 
237 {
238  if ( !( event->possibleActions() & Qt::CopyAction ) )
239  {
240  event->ignore();
241  return;
242  }
243 
244  if ( QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
245  {
246  // dropped a map layer
247  setFocus( Qt::MouseFocusReason );
248  event->setDropAction( Qt::CopyAction );
249  event->accept();
250 
251  if ( layer->crs().isValid() )
252  setCrs( layer->crs() );
253  }
254  else
255  {
256  event->ignore();
257  }
258  mCrsComboBox->setHighlighted( false );
259  update();
260 }
261 
262 void QgsProjectionSelectionWidget::addNotSetOption()
263 {
264  mCrsComboBox->insertItem( 0, mNotSetText, QgsProjectionSelectionWidget::CrsNotSet );
265  if ( !mCrs.isValid() )
266  whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
267 }
268 
269 void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
270 {
271  switch ( static_cast< CrsOption >( mCrsComboBox->itemData( idx ).toInt() ) )
272  {
274  emit crsChanged( mLayerCrs );
275  break;
277  emit crsChanged( mProjectCrs );
278  break;
280  emit crsChanged( mCrs );
281  break;
283  emit crsChanged( mDefaultCrs );
284  break;
286  {
287  long srsid = mCrsComboBox->itemData( idx, Qt::UserRole + 1 ).toLongLong();
289  emit crsChanged( crs );
290  break;
291  }
293  emit cleared();
295  break;
296  }
297  updateTooltip();
298 }
299 
301 {
302  if ( crs.isValid() )
303  {
306  mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
307  crsOptionText( crs ) );
308  mCrsComboBox->blockSignals( true );
309  mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ) );
310  mCrsComboBox->blockSignals( false );
311  }
312  else
313  {
314  int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet );
315  if ( crsNotSetIndex >= 0 )
316  {
317  mCrsComboBox->blockSignals( true );
318  mCrsComboBox->setCurrentIndex( crsNotSetIndex );
319  mCrsComboBox->blockSignals( false );
320  }
321  else
322  {
323  mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
324  crsOptionText( crs ) );
325  }
326  }
327  if ( mCrs != crs )
328  {
329  mCrs = crs;
330  emit crsChanged( crs );
331  }
332  updateTooltip();
333 }
334 
336 {
337  int layerItemIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::LayerCrs );
338  if ( crs.isValid() )
339  {
340  if ( layerItemIndex > -1 )
341  {
342  mCrsComboBox->setItemText( layerItemIndex, tr( "Layer CRS: %1" ).arg( crs.userFriendlyIdentifier() ) );
343  }
344  else
345  {
346  mCrsComboBox->insertItem( firstRecentCrsIndex(), tr( "Layer CRS: %1" ).arg( crs.userFriendlyIdentifier() ), QgsProjectionSelectionWidget::LayerCrs );
347  }
348  }
349  else
350  {
351  if ( layerItemIndex > -1 )
352  {
353  mCrsComboBox->removeItem( layerItemIndex );
354  }
355  }
356  mLayerCrs = crs;
357 }
358 
359 void QgsProjectionSelectionWidget::addProjectCrsOption()
360 {
361  if ( mProjectCrs.isValid() )
362  {
363  mCrsComboBox->addItem( tr( "Project CRS: %1" ).arg( mProjectCrs.userFriendlyIdentifier() ), QgsProjectionSelectionWidget::ProjectCrs );
364  }
365 }
366 
367 void QgsProjectionSelectionWidget::addDefaultCrsOption()
368 {
369  mCrsComboBox->addItem( tr( "Default CRS: %1" ).arg( mDefaultCrs.userFriendlyIdentifier() ), QgsProjectionSelectionWidget::DefaultCrs );
370 }
371 
372 void QgsProjectionSelectionWidget::addCurrentCrsOption()
373 {
374  int index = optionVisible( CrsNotSet ) ? 1 : 0;
375  mCrsComboBox->insertItem( index, crsOptionText( mCrs ), QgsProjectionSelectionWidget::CurrentCrs );
376 
377 }
378 
380 {
381  if ( crs.isValid() )
382  return crs.userFriendlyIdentifier();
383  else
384  return tr( "invalid projection" );
385 }
386 
387 void QgsProjectionSelectionWidget::addRecentCrs()
388 {
389  const QList< QgsCoordinateReferenceSystem> recentProjections = QgsCoordinateReferenceSystem::recentCoordinateReferenceSystems();
390  for ( const QgsCoordinateReferenceSystem &crs : recentProjections )
391  {
392  long srsid = crs.srsid();
393 
394  //check if already shown
395  if ( crsIsShown( srsid ) )
396  {
397  continue;
398  }
399 
400  if ( crs.isValid() )
401  {
403  mCrsComboBox->setItemData( mCrsComboBox->count() - 1, QVariant( ( long long )srsid ), Qt::UserRole + 1 );
404  }
405  }
406 }
407 
408 bool QgsProjectionSelectionWidget::crsIsShown( const long srsid ) const
409 {
410  return srsid == mLayerCrs.srsid() || srsid == mDefaultCrs.srsid() || srsid == mProjectCrs.srsid();
411 }
412 
413 int QgsProjectionSelectionWidget::firstRecentCrsIndex() const
414 {
415  for ( int i = 0; i < mCrsComboBox->count(); ++i )
416  {
417  if ( static_cast< CrsOption >( mCrsComboBox->itemData( i ).toInt() ) == RecentCrs )
418  {
419  return i;
420  }
421  }
422  return -1;
423 }
424 
425 void QgsProjectionSelectionWidget::updateTooltip()
426 {
428  if ( c.isValid() )
429  setToolTip( c.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED, true ) );
430  else
431  setToolTip( QString() );
432 }
433 
434 QgsMapLayer *QgsProjectionSelectionWidget::mapLayerFromMimeData( const QMimeData *data ) const
435 {
437  for ( const QgsMimeDataUtils::Uri &u : uriList )
438  {
439  // is this uri from the current project?
440  if ( QgsMapLayer *layer = u.mapLayer() )
441  {
442  return layer;
443  }
444  }
445  return nullptr;
446 }
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:626
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:1338
QgsSettings::App
@ App
Definition: qgssettings.h:75
QgsProjectionSelectionDialog::setNotSetText
void setNotSetText(const QString &text)
Sets the text to show for the not set option.
Definition: qgsprojectionselectiondialog.cpp:75
QgsCoordinateReferenceSystem::WKT_PREFERRED
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition: qgscoordinatereferencesystem.h:679
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:51
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
A generic dialog to prompt the user for a Coordinate Reference System.
Definition: qgsprojectionselectiondialog.h:52
QgsProjectionSelectionDialog::setShowNoProjection
void setShowNoProjection(bool show)
Sets whether a "no/invalid" projection option should be shown.
Definition: qgsprojectionselectiondialog.cpp:65
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:80
QgsProjectionSelectionDialog::setMessage
void setMessage(const QString &message)
Sets a message to show in the dialog.
Definition: qgsprojectionselectiondialog.cpp:50
geoEpsgCrsAuthId
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
Definition: qgis.h:709
QgsProject::instance
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:468
QgsProjectionSelectionDialog::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the initial crs to show within the dialog.
Definition: qgsprojectionselectiondialog.cpp:85
QgsSettings
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
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:236
QgsProjectionSelectionWidget::setLayerCrs
void setLayerCrs(const QgsCoordinateReferenceSystem &crs)
Sets the layer CRS for the widget.
Definition: qgsprojectionselectionwidget.cpp:335
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:1311
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:1321
QgsHighlightableComboBox
A QComboBox subclass with the ability to "highlight" the edges of the widget.
Definition: qgshighlightablecombobox.h:35
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:924
QgsProjectionSelectionWidget::setCrs
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the current CRS for the widget.
Definition: qgsprojectionselectionwidget.cpp:300
QgsProjectionSelectionWidget::RecentCrs
@ RecentCrs
Recently used CRS.
Definition: qgsprojectionselectionwidget.h:52
QgsMimeDataUtils::Uri
Definition: qgsmimedatautils.h:41
QgsProjectionSelectionWidget::CrsNotSet
@ CrsNotSet
Not set (hidden by default)
Definition: qgsprojectionselectionwidget.h:53
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
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:211
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
Base class for all map layer types.
Definition: qgsmaplayer.h:83
QgsProjectionSelectionWidget::crsOptionText
static QString crsOptionText(const QgsCoordinateReferenceSystem &crs)
Returns display text for the specified crs.
Definition: qgsprojectionselectionwidget.cpp:379
qgssettings.h
QgsProjectionSelectionWidget::dragLeaveEvent
void dragLeaveEvent(QDragLeaveEvent *event) override
Definition: qgsprojectionselectionwidget.cpp:222
QgsProjectionSelectionWidget::CrsOption
CrsOption
Predefined CRS options shown in widget.
Definition: qgsprojectionselectionwidget.h:47
QgsProject::crs
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:100
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:200
QgsCoordinateReferenceSystem::recentCoordinateReferenceSystems
static QList< QgsCoordinateReferenceSystem > recentCoordinateReferenceSystems()
Returns a list of recently used CRS.
Definition: qgscoordinatereferencesystem.cpp:3594