QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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"
23 
25  : QWidget( parent )
26 {
27 
28 
29  QHBoxLayout *layout = new QHBoxLayout();
30  layout->setContentsMargins( 0, 0, 0, 0 );
31  layout->setSpacing( 6 );
32  setLayout( layout );
33 
34  mCrsComboBox = new QComboBox( this );
35  mCrsComboBox->addItem( tr( "invalid projection" ), QgsProjectionSelectionWidget::CurrentCrs );
36  mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
37 
38  mProjectCrs = QgsProject::instance()->crs();
39  addProjectCrsOption();
40 
41  QgsSettings settings;
42  mDefaultCrs = QgsCoordinateReferenceSystem( settings.value( QStringLiteral( "/projections/defaultProjectCrs" ), GEO_EPSG_CRS_AUTHID, QgsSettings::App ).toString() );
43  if ( mDefaultCrs.authid() != mProjectCrs.authid() )
44  {
45  //only show default CRS option if it's different to the project CRS, avoids
46  //needlessly cluttering the widget
47  addDefaultCrsOption();
48  }
49 
50  addRecentCrs();
51 
52  layout->addWidget( mCrsComboBox );
53 
54  mButton = new QToolButton( this );
55  mButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionSetProjection.svg" ) ) );
56  mButton->setToolTip( tr( "Select CRS" ) );
57  layout->addWidget( mButton );
58 
59  setFocusPolicy( Qt::StrongFocus );
60  setFocusProxy( mButton );
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 ( ( 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::addNotSetOption()
198 {
199  mCrsComboBox->insertItem( 0, mNotSetText, QgsProjectionSelectionWidget::CrsNotSet );
200  if ( !mCrs.isValid() )
201  whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
202 }
203 
204 void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
205 {
206  switch ( ( CrsOption )mCrsComboBox->itemData( idx ).toInt() )
207  {
209  emit crsChanged( mLayerCrs );
210  return;
212  emit crsChanged( mProjectCrs );
213  return;
215  emit crsChanged( mCrs );
216  return;
218  emit crsChanged( mDefaultCrs );
219  return;
221  {
222  long srsid = mCrsComboBox->itemData( idx, Qt::UserRole + 1 ).toLongLong();
224  emit crsChanged( crs );
225  return;
226  }
228  emit cleared();
230  return;
231  }
232 }
233 
235 {
236  if ( crs.isValid() )
237  {
240  mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
241  currentCrsOptionText( crs ) );
242  mCrsComboBox->blockSignals( true );
243  mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ) );
244  mCrsComboBox->blockSignals( false );
245  }
246  else
247  {
248  int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet );
249  if ( crsNotSetIndex >= 0 )
250  {
251  mCrsComboBox->blockSignals( true );
252  mCrsComboBox->setCurrentIndex( crsNotSetIndex );
253  mCrsComboBox->blockSignals( false );
254  }
255  else
256  {
257  mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
258  currentCrsOptionText( crs ) );
259  }
260  }
261  if ( mCrs != crs )
262  {
263  mCrs = crs;
264  emit crsChanged( crs );
265  }
266 }
267 
269 {
270  int layerItemIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::LayerCrs );
271  if ( crs.isValid() )
272  {
273  if ( layerItemIndex > -1 )
274  {
275  mCrsComboBox->setItemText( layerItemIndex, tr( "Layer CRS: %1 - %2" ).arg( crs.authid(), crs.description() ) );
276  }
277  else
278  {
279  mCrsComboBox->insertItem( firstRecentCrsIndex(), tr( "Layer CRS: %1 - %2" ).arg( crs.authid(), crs.description() ), QgsProjectionSelectionWidget::LayerCrs );
280  }
281  }
282  else
283  {
284  if ( layerItemIndex > -1 )
285  {
286  mCrsComboBox->removeItem( layerItemIndex );
287  }
288  }
289  mLayerCrs = crs;
290 }
291 
292 void QgsProjectionSelectionWidget::addProjectCrsOption()
293 {
294  if ( mProjectCrs.isValid() )
295  {
296  mCrsComboBox->addItem( tr( "Project CRS: %1 - %2" ).arg( mProjectCrs.authid(), mProjectCrs.description() ), QgsProjectionSelectionWidget::ProjectCrs );
297  }
298 }
299 
300 void QgsProjectionSelectionWidget::addDefaultCrsOption()
301 {
302  mCrsComboBox->addItem( tr( "Default CRS: %1 - %2" ).arg( mDefaultCrs.authid(), mDefaultCrs.description() ), QgsProjectionSelectionWidget::DefaultCrs );
303 }
304 
305 void QgsProjectionSelectionWidget::addCurrentCrsOption()
306 {
307  int index = optionVisible( CrsNotSet ) ? 1 : 0;
308  mCrsComboBox->insertItem( index, currentCrsOptionText( mCrs ), QgsProjectionSelectionWidget::CurrentCrs );
309 
310 }
311 
312 QString QgsProjectionSelectionWidget::currentCrsOptionText( const QgsCoordinateReferenceSystem &crs ) const
313 {
314  if ( crs.isValid() )
315  return tr( "%1 - %2" ).arg( crs.authid(), crs.description() );
316  else
317  return tr( "invalid projection" );
318 }
319 
320 void QgsProjectionSelectionWidget::addRecentCrs()
321 {
322  QStringList recentProjections = QgsCoordinateReferenceSystem::recentProjections();
323  int i = 0;
324  Q_FOREACH ( const QString &projection, recentProjections )
325  {
326  long srsid = projection.toLong();
327 
328  //check if already shown
329  if ( crsIsShown( srsid ) )
330  {
331  continue;
332  }
333 
334  i++;
336  if ( crs.isValid() )
337  {
338  mCrsComboBox->addItem( tr( "%1 - %2" ).arg( crs.authid(), crs.description() ), QgsProjectionSelectionWidget::RecentCrs );
339  mCrsComboBox->setItemData( mCrsComboBox->count() - 1, QVariant( ( long long )srsid ), Qt::UserRole + 1 );
340  }
341  if ( i >= 4 )
342  {
343  //limit to 4 recent projections to avoid clutter
344  break;
345  }
346  }
347 }
348 
349 bool QgsProjectionSelectionWidget::crsIsShown( const long srsid ) const
350 {
351  return srsid == mLayerCrs.srsid() || srsid == mDefaultCrs.srsid() || srsid == mProjectCrs.srsid();
352 }
353 
354 int QgsProjectionSelectionWidget::firstRecentCrsIndex() const
355 {
356  for ( int i = 0; i < mCrsComboBox->count(); ++i )
357  {
358  if ( ( CrsOption )mCrsComboBox->itemData( i ).toInt() == RecentCrs )
359  {
360  return i;
361  }
362  }
363  return -1;
364 }
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the current CRS for the widget.
QgsCoordinateReferenceSystem crs() const
Returns the CRS currently selected in the widget.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
long srsid() const
Returns the internal CRS ID, if available.
Current project CRS (if OTF reprojection enabled)
void setMessage(const QString &message)
Sets a message to show in the dialog.
bool optionVisible(CrsOption option) const
Returns whether the specified CRS option is visible in the widget.
void setNotSetText(const QString &text)
Sets the text to show for the not set option.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
void setShowNoProjection(bool show)
Sets whether a "no/invalid" projection option should be shown.
QgsProjectionSelectionWidget(QWidget *parent=nullptr)
Constructor for QgsProjectionSelectionWidget.
A generic dialog to prompt the user for a Coordinate Reference System.
CrsOption
Predefined CRS options shown in widget.
QgsCoordinateReferenceSystem crs() const
Returns the currently selected CRS for the widget.
void selectCrs()
Opens the dialog for selecting a new CRS.
static QStringList recentProjections()
Returns a list of recently used projections.
void setMessage(const QString &text)
Sets a message to show in the dialog.
QgsCoordinateReferenceSystem crs
Definition: qgsproject.h:95
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
Definition: qgis.cpp:69
void cleared()
Emitted when the not set option is selected.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the initial crs to show within the dialog.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:225
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:411
This class represents a coordinate reference system (CRS).
QString authid() const
Returns the authority identifier for the CRS.
QString description() const
Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".
void setOptionVisible(CrsOption option, bool visible)
Sets whether a predefined CRS option should be shown in the widget.
static QgsCoordinateReferenceSystem fromSrsId(long srsId)
Creates a CRS from a specified QGIS SRS ID.
void setLayerCrs(const QgsCoordinateReferenceSystem &crs)
Sets the layer CRS for the widget.