QGIS API Documentation  3.27.0-Master (bef583a8ef)
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.
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:180
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:2902
const QgsCoordinateReferenceSystem & crs