QGIS API Documentation  3.23.0-Master (4fd2f04bd0)
qgsprojectionselectiondialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgenericprojectionselector.cpp
3  Set user defined CRS using projection selector widget
4  -------------------
5  begin : May 28, 2004
6  copyright : (C) 2004 by Gary E.Sherman
7  email : sherman at mrcc.com
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 #include "qgsapplication.h"
19 #include "qgssettings.h"
20 
22 #include "qgshelp.h"
23 #include <QDialogButtonBox>
24 #include <QApplication>
25 #include "qgsgui.h"
26 #include <QPushButton>
27 
28 
29 //
30 // QgsCrsSelectionWidget
31 //
33  : QgsPanelWidget( parent )
34 {
35  setupUi( this );
36 
37  //we will show this only when a message is set
38  textEdit->hide();
39 
40  mNotSetText = tr( "No CRS (or unknown/non-Earth projection)" );
41  mLabelNoCrs->setText( tr( "Use this option to treat all coordinates as Cartesian coordinates in an unknown reference system." ) );
42 
43  mComboCrsType->addItem( tr( "Predefined CRS" ), static_cast< int >( CrsType::Predefined ) );
44  mComboCrsType->addItem( tr( "Custom CRS" ), static_cast< int >( CrsType::Custom ) );
45 
46  mStackedWidget->setCurrentWidget( mPageDatabase );
47  mComboCrsType->setCurrentIndex( mComboCrsType->findData( static_cast< int >( CrsType::Predefined ) ) );
48 
49  connect( mComboCrsType, qOverload< int >( &QComboBox::currentIndexChanged ), this, [ = ]( int )
50  {
51  if ( !mComboCrsType->currentData().isValid() )
52  mStackedWidget->setCurrentWidget( mPageNoCrs );
53  else
54  {
55  switch ( static_cast< CrsType >( mComboCrsType->currentData().toInt() ) )
56  {
57  case QgsCrsSelectionWidget::CrsType::Predefined:
58  mStackedWidget->setCurrentWidget( mPageDatabase );
59  break;
60  case QgsCrsSelectionWidget::CrsType::Custom:
61  mStackedWidget->setCurrentWidget( mPageCustom );
62  break;
63  }
64  }
65 
66  if ( !mBlockSignals )
67  {
68  emit crsChanged();
70  }
71  } );
72 
73  connect( projectionSelector, &QgsProjectionSelectionTreeWidget::projectionDoubleClicked, this, [ = ]
74  {
75  emit crsDoubleClicked( projectionSelector->crs() );
76  } );
77 
78  connect( mCrsDefinitionWidget, &QgsCrsDefinitionWidget::crsChanged, this, [ = ]()
79  {
80  if ( !mBlockSignals )
81  {
82  emit crsChanged();
83  emit hasValidSelectionChanged( hasValidSelection() );
84  }
85  } );
86 
87  connect( projectionSelector, &QgsProjectionSelectionTreeWidget::crsSelected, this, [ = ]()
88  {
89  if ( !mBlockSignals )
90  {
91  emit crsChanged();
92  emit hasValidSelectionChanged( hasValidSelection() );
93  }
94  } );
95 
96  connect( projectionSelector, &QgsProjectionSelectionTreeWidget::hasValidSelectionChanged, this, [ = ]()
97  {
98  if ( !mBlockSignals )
99  {
100  emit crsChanged();
101  emit hasValidSelectionChanged( hasValidSelection() );
102  }
103  } );
104 
105  const QgsSettings settings;
106  mSplitter->restoreState( settings.value( QStringLiteral( "Windows/ProjectionSelectorDialog/splitterState" ) ).toByteArray() );
107 }
108 
110 {
111  QgsSettings settings;
112  settings.setValue( QStringLiteral( "Windows/ProjectionSelectorDialog/splitterState" ), mSplitter->saveState() );
113 }
114 
115 void QgsCrsSelectionWidget::setMessage( const QString &message )
116 {
117  textEdit->setHtml( QStringLiteral( "<head><style>%1</style></head><body>%2</body>" ).arg( QgsApplication::reportStyleSheet(),
118  message ) );
119  textEdit->show();
120 }
121 
123 {
124  if ( mShowNoCrsOption == show )
125  return;
126 
127  mBlockSignals++;
128  mShowNoCrsOption = show;
129  if ( mShowNoCrsOption )
130  {
131  mComboCrsType->insertItem( 0, mNotSetText );
132  }
133  else
134  {
135  mComboCrsType->removeItem( 0 );
136  }
137 
138  if ( show && mDeferredInvalidCrsSet )
139  {
140  mComboCrsType->setCurrentIndex( 0 );
141  }
142 
143  mBlockSignals--;
144 
145  if ( mDeferredInvalidCrsSet )
146  emit crsChanged();
147 
148  mDeferredInvalidCrsSet = false;
149 
151 }
152 
154 {
155  return mShowNoCrsOption;
156 }
157 
158 void QgsCrsSelectionWidget::setNotSetText( const QString &text, const QString &description )
159 {
160  mNotSetText = text;
161 
162  if ( mShowNoCrsOption )
163  {
164  mComboCrsType->setItemText( 0, mNotSetText );
165  }
166 
167  mLabelNoCrs->setText( description.isEmpty() ? text : description );
168 }
169 
171 {
172  if ( !mComboCrsType->currentData().isValid() )
173  return true;
174  else if ( mDeferredInvalidCrsSet )
175  return false;
176  else
177  {
178  switch ( static_cast< CrsType >( mComboCrsType->currentData().toInt() ) )
179  {
180  case QgsCrsSelectionWidget::CrsType::Predefined:
181  return projectionSelector->hasValidSelection();
182  case QgsCrsSelectionWidget::CrsType::Custom:
183  return mCrsDefinitionWidget->crs().isValid();
184  }
186  }
187 }
188 
190 {
191  if ( !mComboCrsType->currentData().isValid() )
193  else
194  {
195  switch ( static_cast< CrsType >( mComboCrsType->currentData().toInt() ) )
196  {
197  case QgsCrsSelectionWidget::CrsType::Predefined:
198  return projectionSelector->crs();
199  case QgsCrsSelectionWidget::CrsType::Custom:
200  return mCrsDefinitionWidget->crs();
201  }
203  }
204 }
205 
207 {
208  mBlockSignals++;
209  if ( !crs.isValid() )
210  {
211  if ( mShowNoCrsOption )
212  mComboCrsType->setCurrentIndex( 0 );
213  else
214  mDeferredInvalidCrsSet = true;
215  }
216  else
217  {
218  projectionSelector->setCrs( crs );
219  mCrsDefinitionWidget->setCrs( crs );
220  if ( crs.isValid() && crs.authid().isEmpty() )
221  {
222  mComboCrsType->setCurrentIndex( mComboCrsType->findData( static_cast< int>( CrsType::Custom ) ) );
223  mStackedWidget->setCurrentWidget( mPageCustom );
224  }
225  else
226  {
227  mComboCrsType->setCurrentIndex( mComboCrsType->findData( static_cast< int>( CrsType::Predefined ) ) );
228  mStackedWidget->setCurrentWidget( mPageDatabase );
229  }
230  }
231  mBlockSignals--;
232 
233  emit crsChanged();
235 }
236 
237 void QgsCrsSelectionWidget::setOgcWmsCrsFilter( const QSet<QString> &crsFilter )
238 {
239  projectionSelector->setOgcWmsCrsFilter( crsFilter );
240 }
241 
242 
243 
244 //
245 // QgsProjectionSelectionDialog
246 //
247 
249  Qt::WindowFlags fl )
250  : QDialog( parent, fl )
251 {
252  QVBoxLayout *vlayout = new QVBoxLayout();
253 
254  mCrsWidget = new QgsCrsSelectionWidget();
255  vlayout->addWidget( mCrsWidget, 1 );
256 
257  mButtonBox = new QDialogButtonBox( QDialogButtonBox::Cancel | QDialogButtonBox::Help | QDialogButtonBox::Ok );
258  connect( mButtonBox, &QDialogButtonBox::accepted, this, &QgsProjectionSelectionDialog::accept );
259  connect( mButtonBox, &QDialogButtonBox::rejected, this, &QgsProjectionSelectionDialog::reject );
260  connect( mButtonBox, &QDialogButtonBox::helpRequested, this, &QgsProjectionSelectionDialog::showHelp );
261 
262  vlayout->addWidget( mButtonBox );
263 
264  setLayout( vlayout );
265 
267 
268  //apply selected projection upon double-click on item
269  connect( mCrsWidget, &QgsCrsSelectionWidget::crsDoubleClicked, this, &QgsProjectionSelectionDialog::accept );
270 }
271 
272 void QgsProjectionSelectionDialog::setMessage( const QString &message )
273 {
274  mCrsWidget->setMessage( message );
275 }
276 
278 {
279  setMessage( tr( "This layer appears to have no projection specification." )
280  + ' '
281  + tr( "By default, this layer will now have its projection set to that of the project, "
282  "but you may override this by selecting a different projection below." ) );
283 }
284 
286 {
287  mCrsWidget->setShowNoCrs( show );
288 }
289 
291 {
292  return mCrsWidget->showNoCrs();
293 }
294 
295 void QgsProjectionSelectionDialog::setNotSetText( const QString &text, const QString &description )
296 {
297  mCrsWidget->setNotSetText( text, description );
298 }
299 
301 {
302  mRequireValidSelection = true;
303  mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( hasValidSelection() );
304 
305  connect( mCrsWidget, &QgsCrsSelectionWidget::hasValidSelectionChanged, this, [ = ]( bool isValid )
306  {
307  mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( isValid );
308  } );
309 }
310 
312 {
313  return mCrsWidget->hasValidSelection();
314 }
315 
317 {
318  return mCrsWidget->crs();
319 }
320 
322 {
323  mCrsWidget->setCrs( crs );
324 
325  if ( mRequireValidSelection )
326  mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( hasValidSelection() );
327 }
328 
329 void QgsProjectionSelectionDialog::setOgcWmsCrsFilter( const QSet<QString> &crsFilter )
330 {
331  mCrsWidget->setOgcWmsCrsFilter( crsFilter );
332 }
333 
334 void QgsProjectionSelectionDialog::showHelp()
335 {
336  QgsHelp::openHelp( QStringLiteral( "working_with_projections/working_with_projections.html" ) );
337 }
static QString reportStyleSheet(QgsApplication::StyleSheetType styleSheetType=QgsApplication::StyleSheetType::Qt)
Returns a css style sheet for reports, the styleSheetType argument determines what type of stylesheet...
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString authid() const
Returns the authority identifier for the CRS.
void crsChanged()
Emitted when the CRS defined in the widget is changed.
A generic widget allowing users to pick a Coordinate Reference System (or define their own).
bool showNoCrs() const
Returns whether the "no/invalid" CRS option is shown.
QgsCoordinateReferenceSystem crs() const
Returns the CRS currently selected in the widget.
void hasValidSelectionChanged(bool isValid)
Emitted when the widget has a valid selection or not.
void crsDoubleClicked(const QgsCoordinateReferenceSystem &crs)
Emitted when a CRS entry in the widget is double-clicked.
void setShowNoCrs(bool show)
Sets whether a "no/invalid" CRS option should be shown.
QgsCrsSelectionWidget(QWidget *parent=nullptr)
Constructor for QgsCrsSelectionWidget, with the specified parent widget.
void crsChanged()
Emitted when the CRS defined in the widget is changed.
void setMessage(const QString &message)
Sets a message to show in the dialog.
bool hasValidSelection() const
Returns true if the widget has a valid CRS defined.
void setNotSetText(const QString &text, const QString &description=QString())
Sets the text to show for the not set option.
void setOgcWmsCrsFilter(const QSet< QString > &crsFilter)
filters this dialog by the given CRSs
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the crs to show within the widget.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
Definition: qgsgui.cpp:174
static void openHelp(const QString &key)
Opens help topic for the given help key using default system web browser.
Definition: qgshelp.cpp:36
Base class for any widget that can be shown as a inline panel.
void showNoCrsForLayerMessage()
When called, the dialog will show a default "layer has no CRS set" message above the projection selec...
void setShowNoProjection(bool show)
Sets whether a "no/invalid" projection option should be shown.
bool showNoProjection() const
Returns whether the "no/invalid" projection option is shown.
bool hasValidSelection() const
Returns true if the dialog has a valid CRS defined.
void setNotSetText(const QString &text, const QString &description=QString())
Sets the text to show for the not set option.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the initial crs to show within the dialog.
void setMessage(const QString &message)
Sets a message to show in the dialog.
QgsCoordinateReferenceSystem crs() const
Returns the CRS currently selected in the widget.
QgsProjectionSelectionDialog(QWidget *parent=nullptr, Qt::WindowFlags fl=QgsGuiUtils::ModalDialogFlags)
Constructor for QgsProjectionSelectionDialog.
void setRequireValidSelection()
Sets the dialog to require a valid selection only, preventing users from accepting the dialog if no s...
void setOgcWmsCrsFilter(const QSet< QString > &crsFilter)
filters this dialog by the given CRSs
void crsSelected()
Emitted when a projection is selected in the widget.
void projectionDoubleClicked()
Emitted when a projection is double clicked in the list.
void hasValidSelectionChanged(bool isValid)
Emitted when the selection in the tree is changed from a valid selection to an invalid selection,...
This class is a composition of two QSettings instances:
Definition: qgssettings.h:62
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
#define BUILTIN_UNREACHABLE
Definition: qgis.h:2129
const QgsCoordinateReferenceSystem & crs