QGIS API Documentation  3.6.0-Noosa (5873452)
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 : denis.rouzaud@gmail.com
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  QString defCrsString = settings.value( QStringLiteral( "Projections/projectDefaultCrs" ), GEO_EPSG_CRS_AUTHID ).toString();
43  mDefaultCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( defCrsString );
44  if ( mDefaultCrs.authid() != mProjectCrs.authid() )
45  {
46  //only show default CRS option if it's different to the project CRS, avoids
47  //needlessly cluttering the widget
48  addDefaultCrsOption();
49  }
50 
51  addRecentCrs();
52 
53  layout->addWidget( mCrsComboBox );
54 
55  mButton = new QToolButton( this );
56  mButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionSetProjection.svg" ) ) );
57  mButton->setToolTip( tr( "Select CRS" ) );
58  layout->addWidget( mButton );
59 
60  setFocusPolicy( Qt::StrongFocus );
61  setFocusProxy( mButton );
62 
63  connect( mButton, &QToolButton::clicked, this, &QgsProjectionSelectionWidget::selectCrs );
64  connect( mCrsComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsProjectionSelectionWidget::comboIndexChanged );
65 }
66 
68 {
69  switch ( ( CrsOption )mCrsComboBox->currentData().toInt() )
70  {
72  return mLayerCrs;
74  return mProjectCrs;
76  return mDefaultCrs;
78  return mCrs;
80  {
81  long srsid = mCrsComboBox->currentData( Qt::UserRole + 1 ).toLongLong();
83  return crs;
84  }
87  }
88  return mCrs;
89 }
90 
92 {
93  int optionIndex = mCrsComboBox->findData( option );
94 
95  if ( visible && optionIndex < 0 )
96  {
97  //add missing CRS option
98  switch ( option )
99  {
101  {
102  setLayerCrs( mLayerCrs );
103  return;
104  }
106  {
107  addProjectCrsOption();
108  return;
109  }
111  {
112  addDefaultCrsOption();
113  return;
114  }
116  {
117  addCurrentCrsOption();
118  return;
119  }
121  //recently used CRS option cannot be readded
122  return;
124  {
125  addNotSetOption();
126 
127  if ( optionVisible( CurrentCrs ) && !mCrs.isValid() )
128  {
129  // hide invalid option if not set option is shown
130  setOptionVisible( CurrentCrs, false );
131  }
132 
133  return;
134  }
135  }
136  }
137  else if ( !visible && optionIndex >= 0 )
138  {
139  //remove CRS option
140  mCrsComboBox->removeItem( optionIndex );
141 
142  if ( option == CrsNotSet )
143  {
144  setOptionVisible( CurrentCrs, true );
145  }
146  }
147 }
148 
150 {
151  mNotSetText = text;
152  int optionIndex = mCrsComboBox->findData( CrsNotSet );
153  if ( optionIndex >= 0 )
154  {
155  mCrsComboBox->setItemText( optionIndex, mNotSetText );
156  }
157 }
158 
159 void QgsProjectionSelectionWidget::setMessage( const QString &text )
160 {
161  mMessage = text;
162 }
163 
165 {
166  int optionIndex = mCrsComboBox->findData( option );
167  return optionIndex >= 0;
168 }
169 
171 {
172  //find out crs id of current proj4 string
173  QgsProjectionSelectionDialog dlg( this );
174  dlg.setMessage( mMessage );
175  if ( mCrs.isValid() )
176  {
177  dlg.setCrs( mCrs );
178  }
179 
180  if ( dlg.exec() )
181  {
182  mCrsComboBox->blockSignals( true );
183  mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ) );
184  mCrsComboBox->blockSignals( false );
186  setCrs( crs );
187  emit crsChanged( crs );
188  }
189  else
190  {
191  QApplication::restoreOverrideCursor();
192  }
193 }
194 
195 void QgsProjectionSelectionWidget::addNotSetOption()
196 {
197  mCrsComboBox->insertItem( 0, mNotSetText, QgsProjectionSelectionWidget::CrsNotSet );
198  if ( !mCrs.isValid() )
199  whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
200 }
201 
202 void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
203 {
204  switch ( ( CrsOption )mCrsComboBox->itemData( idx ).toInt() )
205  {
207  emit crsChanged( mLayerCrs );
208  return;
210  emit crsChanged( mProjectCrs );
211  return;
213  emit crsChanged( mCrs );
214  return;
216  emit crsChanged( mDefaultCrs );
217  return;
219  {
220  long srsid = mCrsComboBox->itemData( idx, Qt::UserRole + 1 ).toLongLong();
222  emit crsChanged( crs );
223  return;
224  }
226  emit cleared();
228  return;
229  }
230 }
231 
233 {
234  if ( crs.isValid() )
235  {
238  mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
239  currentCrsOptionText( crs ) );
240  mCrsComboBox->blockSignals( true );
241  mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ) );
242  mCrsComboBox->blockSignals( false );
243  }
244  else
245  {
246  int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet );
247  if ( crsNotSetIndex >= 0 )
248  {
249  mCrsComboBox->blockSignals( true );
250  mCrsComboBox->setCurrentIndex( crsNotSetIndex );
251  mCrsComboBox->blockSignals( false );
252  }
253  else
254  {
255  mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
256  currentCrsOptionText( crs ) );
257  }
258  }
259  if ( mCrs != crs )
260  {
261  mCrs = crs;
262  emit crsChanged( crs );
263  }
264 }
265 
267 {
268  int layerItemIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::LayerCrs );
269  if ( crs.isValid() )
270  {
271  if ( layerItemIndex > -1 )
272  {
273  mCrsComboBox->setItemText( layerItemIndex, tr( "Layer CRS: %1 - %2" ).arg( crs.authid(), crs.description() ) );
274  }
275  else
276  {
277  mCrsComboBox->insertItem( firstRecentCrsIndex(), tr( "Layer CRS: %1 - %2" ).arg( crs.authid(), crs.description() ), QgsProjectionSelectionWidget::LayerCrs );
278  }
279  }
280  else
281  {
282  if ( layerItemIndex > -1 )
283  {
284  mCrsComboBox->removeItem( layerItemIndex );
285  }
286  }
287  mLayerCrs = crs;
288 }
289 
290 void QgsProjectionSelectionWidget::addProjectCrsOption()
291 {
292  if ( mProjectCrs.isValid() )
293  {
294  mCrsComboBox->addItem( tr( "Project CRS: %1 - %2" ).arg( mProjectCrs.authid(), mProjectCrs.description() ), QgsProjectionSelectionWidget::ProjectCrs );
295  }
296 }
297 
298 void QgsProjectionSelectionWidget::addDefaultCrsOption()
299 {
300  mCrsComboBox->addItem( tr( "Default CRS: %1 - %2" ).arg( mDefaultCrs.authid(), mDefaultCrs.description() ), QgsProjectionSelectionWidget::DefaultCrs );
301 }
302 
303 void QgsProjectionSelectionWidget::addCurrentCrsOption()
304 {
305  int index = optionVisible( CrsNotSet ) ? 1 : 0;
306  mCrsComboBox->insertItem( index, currentCrsOptionText( mCrs ), QgsProjectionSelectionWidget::CurrentCrs );
307 
308 }
309 
310 QString QgsProjectionSelectionWidget::currentCrsOptionText( const QgsCoordinateReferenceSystem &crs ) const
311 {
312  if ( crs.isValid() )
313  return tr( "%1 - %2" ).arg( crs.authid(), crs.description() );
314  else
315  return tr( "invalid projection" );
316 }
317 
318 void QgsProjectionSelectionWidget::addRecentCrs()
319 {
320  QStringList recentProjections = QgsCoordinateReferenceSystem::recentProjections();
321  int i = 0;
322  Q_FOREACH ( const QString &projection, recentProjections )
323  {
324  long srsid = projection.toLong();
325 
326  //check if already shown
327  if ( crsIsShown( srsid ) )
328  {
329  continue;
330  }
331 
332  i++;
334  if ( crs.isValid() )
335  {
336  mCrsComboBox->addItem( tr( "%1 - %2" ).arg( crs.authid(), crs.description() ), QgsProjectionSelectionWidget::RecentCrs );
337  mCrsComboBox->setItemData( mCrsComboBox->count() - 1, QVariant( ( long long )srsid ), Qt::UserRole + 1 );
338  }
339  if ( i >= 4 )
340  {
341  //limit to 4 recent projections to avoid clutter
342  break;
343  }
344  }
345 }
346 
347 bool QgsProjectionSelectionWidget::crsIsShown( const long srsid ) const
348 {
349  return srsid == mLayerCrs.srsid() || srsid == mDefaultCrs.srsid() || srsid == mProjectCrs.srsid();
350 }
351 
352 int QgsProjectionSelectionWidget::firstRecentCrsIndex() const
353 {
354  for ( int i = 0; i < mCrsComboBox->count(); ++i )
355  {
356  if ( ( CrsOption )mCrsComboBox->itemData( i ).toInt() == RecentCrs )
357  {
358  return i;
359  }
360  }
361  return -1;
362 }
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the current CRS for the widget.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:58
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
Current project CRS (if OTF reprojection enabled)
void setMessage(const QString &message)
Sets a message to show in the dialog.
void setNotSetText(const QString &text)
Sets the text to show for the not set option.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
QgsProjectionSelectionWidget(QWidget *parent=nullptr)
Constructor for QgsProjectionSelectionWidget.
QgsCoordinateReferenceSystem crs() const
Returns the CRS currently selected in the widget.
A generic dialog to prompt the user for a Coordinate Reference System.
QgsCoordinateReferenceSystem crs() const
Returns the currently selected CRS for the widget.
CrsOption
Predefined CRS options shown in 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
QString description() const
Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".
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.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:212
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:430
This class represents a coordinate reference system (CRS).
long srsid() const
Returns the internal CRS ID, if available.
bool optionVisible(CrsOption option) const
Returns whether the specified CRS option is visible in the widget.
void setOptionVisible(CrsOption option, bool visible)
Sets whether a predefined CRS option should be shown in the widget.
QString authid() const
Returns the authority identifier for the CRS.
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.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.