QGIS API Documentation  3.0.2-Girona (307d082)
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  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  mCrs = crs;
260 }
261 
263 {
264  int layerItemIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::LayerCrs );
265  if ( crs.isValid() )
266  {
267  if ( layerItemIndex > -1 )
268  {
269  mCrsComboBox->setItemText( layerItemIndex, tr( "Layer CRS: %1 - %2" ).arg( crs.authid(), crs.description() ) );
270  }
271  else
272  {
273  mCrsComboBox->insertItem( firstRecentCrsIndex(), tr( "Layer CRS: %1 - %2" ).arg( crs.authid(), crs.description() ), QgsProjectionSelectionWidget::LayerCrs );
274  }
275  }
276  else
277  {
278  if ( layerItemIndex > -1 )
279  {
280  mCrsComboBox->removeItem( layerItemIndex );
281  }
282  }
283  mLayerCrs = crs;
284 }
285 
286 void QgsProjectionSelectionWidget::addProjectCrsOption()
287 {
288  if ( mProjectCrs.isValid() )
289  {
290  mCrsComboBox->addItem( tr( "Project CRS: %1 - %2" ).arg( mProjectCrs.authid(), mProjectCrs.description() ), QgsProjectionSelectionWidget::ProjectCrs );
291  }
292 }
293 
294 void QgsProjectionSelectionWidget::addDefaultCrsOption()
295 {
296  mCrsComboBox->addItem( tr( "Default CRS: %1 - %2" ).arg( mDefaultCrs.authid(), mDefaultCrs.description() ), QgsProjectionSelectionWidget::DefaultCrs );
297 }
298 
299 void QgsProjectionSelectionWidget::addCurrentCrsOption()
300 {
301  int index = optionVisible( CrsNotSet ) ? 1 : 0;
302  mCrsComboBox->insertItem( index, currentCrsOptionText( mCrs ), QgsProjectionSelectionWidget::CurrentCrs );
303 
304 }
305 
306 QString QgsProjectionSelectionWidget::currentCrsOptionText( const QgsCoordinateReferenceSystem &crs ) const
307 {
308  if ( crs.isValid() )
309  return tr( "%1 - %2" ).arg( crs.authid(), crs.description() );
310  else
311  return tr( "invalid projection" );
312 }
313 
314 void QgsProjectionSelectionWidget::addRecentCrs()
315 {
316  QStringList recentProjections = QgsCoordinateReferenceSystem::recentProjections();
317  int i = 0;
318  Q_FOREACH ( const QString &projection, recentProjections )
319  {
320  long srsid = projection.toLong();
321 
322  //check if already shown
323  if ( crsIsShown( srsid ) )
324  {
325  continue;
326  }
327 
328  i++;
330  if ( crs.isValid() )
331  {
332  mCrsComboBox->addItem( tr( "%1 - %2" ).arg( crs.authid(), crs.description() ), QgsProjectionSelectionWidget::RecentCrs );
333  mCrsComboBox->setItemData( mCrsComboBox->count() - 1, QVariant( ( long long )srsid ), Qt::UserRole + 1 );
334  }
335  if ( i >= 4 )
336  {
337  //limit to 4 recent projections to avoid clutter
338  break;
339  }
340  }
341 }
342 
343 bool QgsProjectionSelectionWidget::crsIsShown( const long srsid ) const
344 {
345  return srsid == mLayerCrs.srsid() || srsid == mDefaultCrs.srsid() || srsid == mProjectCrs.srsid();
346 }
347 
348 int QgsProjectionSelectionWidget::firstRecentCrsIndex() const
349 {
350  for ( int i = 0; i < mCrsComboBox->count(); ++i )
351  {
352  if ( ( CrsOption )mCrsComboBox->itemData( i ).toInt() == RecentCrs )
353  {
354  return i;
355  }
356  }
357  return -1;
358 }
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the current CRS for the widget.
This class is a composition of two QSettings instances:
Definition: qgssettings.h:57
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 setOptionVisible(const CrsOption option, const bool visible)
Sets whether a predefined CRS option should be shown in 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:88
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:224
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.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), const Section section=NoSection) const
Returns the value for setting key.
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:383
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.
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.