QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
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 
18 
20 #include "qgsapplication.h"
22 #include "qgsproject.h"
23 #include "qgscrscache.h"
24 #include <QSettings>
25 
27  : QWidget( parent )
28 {
29  mDialog = new QgsGenericProjectionSelector( this );
30 
32  layout->setContentsMargins( 0, 0, 0, 0 );
33  layout->setSpacing( 0 );
34  setLayout( layout );
35 
36  mCrsComboBox = new QComboBox( this );
37  mCrsComboBox->addItem( tr( "invalid projection" ), QgsProjectionSelectionWidget::CurrentCrs );
38  mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
39 
40  if ( QgsProject::instance()->readNumEntry( "SpatialRefSys", "/ProjectionsEnabled", 0 ) )
41  {
42  //only show project CRS if OTF reprojection is enabled - otherwise the
43  //CRS stored in the project can be misleading
44  QString projectCrsString = QgsProject::instance()->readEntry( "SpatialRefSys", "/ProjectCrs" );
45  mProjectCrs = QgsCRSCache::instance()->crsByOgcWmsCrs( projectCrsString );
46  addProjectCrsOption();
47  }
48 
49  QSettings settings;
50  QString defCrsString = settings.value( "/Projections/projectDefaultCrs", GEO_EPSG_CRS_AUTHID ).toString();
51  mDefaultCrs = QgsCRSCache::instance()->crsByOgcWmsCrs( defCrsString );
52  if ( mDefaultCrs.authid() != mProjectCrs.authid() )
53  {
54  //only show default CRS option if it's different to the project CRS, avoids
55  //needlessly cluttering the widget
56  addDefaultCrsOption();
57  }
58 
59  addRecentCrs();
60 
61  layout->addWidget( mCrsComboBox );
62 
63  mButton = new QToolButton( this );
64  mButton->setIcon( QgsApplication::getThemeIcon( "mActionSetProjection.svg" ) );
65  mButton->setToolTip( tr( "Select CRS" ) );
66  layout->addWidget( mButton );
67 
68  setFocusPolicy( Qt::StrongFocus );
69  setFocusProxy( mButton );
70 
71  connect( mButton, SIGNAL( clicked() ), this, SLOT( selectCrs() ) );
72  connect( mCrsComboBox, SIGNAL( currentIndexChanged( int ) ), this, SLOT( comboIndexChanged( int ) ) );
73 }
74 
76 {
77  switch (( CrsOption )mCrsComboBox->itemData( mCrsComboBox->currentIndex() ).toInt() )
78  {
80  return mLayerCrs;
82  return mProjectCrs ;
84  return mDefaultCrs ;
86  return mCrs;
88  {
89  long srsid = mCrsComboBox->itemData( mCrsComboBox->currentIndex(), Qt::UserRole + 1 ).toLongLong();
91  return crs;
92  }
93  }
94  return mCrs;
95 }
96 
98 {
99  int optionIndex = mCrsComboBox->findData( option );
100 
101  if ( visible && optionIndex < 0 )
102  {
103  //add missing CRS option
104  switch ( option )
105  {
107  {
108  setLayerCrs( mLayerCrs );
109  return;
110  }
112  {
113  addProjectCrsOption();
114  return;
115  }
117  {
118  addDefaultCrsOption();
119  return;
120  }
123  //current/recently used CRS option cannot be readded
124  return;
125  }
126  }
127  else if ( !visible && optionIndex >= 0 )
128  {
129  //remove CRS option
130  mCrsComboBox->removeItem( optionIndex );
131  }
132 }
133 
135 {
136  //find out crs id of current proj4 string
137  if ( mCrs.isValid() )
138  {
139  mDialog->setSelectedCrsId( mCrs.srsid() );
140  }
141 
142  if ( mDialog->exec() )
143  {
144  mCrsComboBox->blockSignals( true );
145  mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ) );
146  mCrsComboBox->blockSignals( false );
148  setCrs( crs );
149  emit crsChanged( crs );
150  }
151  else
152  {
154  }
155 }
156 
157 void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
158 {
159  switch (( CrsOption )mCrsComboBox->itemData( idx ).toInt() )
160  {
162  emit crsChanged( mLayerCrs );
163  return;
165  emit crsChanged( mProjectCrs );
166  return;
168  emit crsChanged( mCrs );
169  return;
171  emit crsChanged( mDefaultCrs );
172  return;
174  {
175  long srsid = mCrsComboBox->itemData( idx, Qt::UserRole + 1 ).toLongLong();
177  emit crsChanged( crs );
178  return;
179  }
180  }
181 }
182 
184 {
185  if ( crs.isValid() )
186  {
187  mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
188  tr( "Selected CRS (%1, %2)" ).arg( crs.authid(), crs.description() ) );
189  mCrsComboBox->blockSignals( true );
190  mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ) );
191  mCrsComboBox->blockSignals( false );
192  }
193  else
194  {
195  mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
196  tr( "invalid projection" ) );
197  }
198  mCrs = crs;
199 }
200 
202 {
203  int layerItemIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::LayerCrs );
204  if ( crs.isValid() )
205  {
206  if ( layerItemIndex > -1 )
207  {
208  mCrsComboBox->setItemText( layerItemIndex, tr( "Layer CRS (%1, %2)" ).arg( crs.authid(), crs.description() ) );
209  }
210  else
211  {
212  mCrsComboBox->insertItem( firstRecentCrsIndex(), tr( "Layer CRS (%1, %2)" ).arg( crs.authid(), crs.description() ), QgsProjectionSelectionWidget::LayerCrs );
213  }
214  }
215  else
216  {
217  if ( layerItemIndex > -1 )
218  {
219  mCrsComboBox->removeItem( layerItemIndex );
220  }
221  }
222  mLayerCrs = crs;
223 }
224 
225 void QgsProjectionSelectionWidget::addProjectCrsOption()
226 {
227  if ( mProjectCrs.isValid() )
228  {
229  mCrsComboBox->addItem( tr( "Project CRS (%1 - %2)" ).arg( mProjectCrs.authid(), mProjectCrs.description() ), QgsProjectionSelectionWidget::ProjectCrs );
230  }
231 }
232 
233 void QgsProjectionSelectionWidget::addDefaultCrsOption()
234 {
235  mCrsComboBox->addItem( tr( "Default CRS (%1 - %2)" ).arg( mDefaultCrs.authid(), mDefaultCrs.description() ), QgsProjectionSelectionWidget::DefaultCrs );
236 }
237 
238 void QgsProjectionSelectionWidget::addRecentCrs()
239 {
241  int i = 0;
242  Q_FOREACH ( const QString& projection, recentProjections )
243  {
244  long srsid = projection.toLong();
245 
246  //check if already shown
247  if ( crsIsShown( srsid ) )
248  {
249  continue;
250  }
251 
252  i++;
254  if ( crs.isValid() )
255  {
256  mCrsComboBox->addItem( tr( "%1 - %2" ).arg( crs.authid(), crs.description() ), QgsProjectionSelectionWidget::RecentCrs );
257  mCrsComboBox->setItemData( mCrsComboBox->count() - 1, QVariant(( long long )srsid ), Qt::UserRole + 1 );
258  }
259  if ( i >= 4 )
260  {
261  //limit to 4 recent projections to avoid clutter
262  break;
263  }
264  }
265 }
266 
267 bool QgsProjectionSelectionWidget::crsIsShown( const long srsid ) const
268 {
269  return srsid == mLayerCrs.srsid() || srsid == mDefaultCrs.srsid() || srsid == mProjectCrs.srsid();
270 }
271 
272 int QgsProjectionSelectionWidget::firstRecentCrsIndex() const
273 {
274  for ( int i = 0; i < mCrsComboBox->count(); ++i )
275  {
276  if (( CrsOption )mCrsComboBox->itemData( i ).toInt() == RecentCrs )
277  {
278  return i;
279  }
280  }
281  return -1;
282 }
QLayout * layout() const
qlonglong toLongLong(bool *ok) const
void setContentsMargins(int left, int top, int right, int bottom)
QString readEntry(const QString &scope, const QString &key, const QString &def=QString::null, bool *ok=nullptr) const
QgsCoordinateReferenceSystem crsByOgcWmsCrs(const QString &ogcCrs) const
Returns the CRS from a given OGC WMS-format Coordinate Reference System string.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the current CRS for the widget.
void setFocusPolicy(Qt::FocusPolicy policy)
static QIcon getThemeIcon(const QString &theName)
Helper to get a theme icon.
A generic dialog to prompt the user for a Coordinate Reference System.
int exec()
void setIcon(const QIcon &icon)
QString tr(const char *sourceText, const char *disambiguation, int n)
void setItemText(int index, const QString &text)
QgsProjectionSelectionWidget(QWidget *parent=nullptr)
void insertItem(int index, const QString &text, const QVariant &userData)
QgsCoordinateReferenceSystem crsBySrsId(long srsId) const
Returns the CRS from a specified QGIS SRS ID.
void addItem(const QString &text, const QVariant &userData)
QgsCoordinateReferenceSystem crs() const
Returns the currently selected CRS for the widget.
CrsOption
Predefined CRS options shown in widget.
void addWidget(QWidget *widget, int stretch, QFlags< Qt::AlignmentFlag > alignment)
void setOptionVisible(const CrsOption option, const bool visible)
Sets whether a predefined CRS option should be shown in the widget.
void setLayout(QLayout *layout)
int toInt(bool *ok) const
void selectCrs()
Opens the dialog for selecting a new CRS.
static QStringList recentProjections()
Returns a list of recently used projections.
void setFocusProxy(QWidget *w)
QString description() const
Returns the descriptive name of the CRS, eg "WGS 84" or "GDA 94 / Vicgrid94".
void restoreOverrideCursor()
const QString GEO_EPSG_CRS_AUTHID
Geographic coord sys from EPSG authority.
Definition: qgis.cpp:74
void setSizePolicy(QSizePolicy)
QVariant itemData(int index, int role) const
bool blockSignals(bool block)
long toLong(bool *ok, int base) const
QVariant value(const QString &key, const QVariant &defaultValue) const
void removeItem(int index)
int findData(const QVariant &data, int role, QFlags< Qt::MatchFlag > flags) const
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
void setItemData(int index, const QVariant &value, int role)
static QgsProject * instance()
Returns the QgsProject singleton instance.
Definition: qgsproject.cpp:382
Class for storing a coordinate reference system (CRS)
void setToolTip(const QString &)
long srsid() const
Returns the SrsId, if available.
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QString toString() const
static QgsCRSCache * instance()
Returns a pointer to the QgsCRSCache singleton.
Definition: qgscrscache.cpp:91
void setSpacing(int spacing)
QString authid() const
Returns the authority identifier for the CRS, which includes both the authority (eg EPSG) and the CRS...
void setLayerCrs(const QgsCoordinateReferenceSystem &crs)
Sets the layer CRS for the widget.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.