Skip to content
Permalink
Browse files
Add "Custom CRS" tab to projection selection dialog
This allows users to just directly enter a custom CRS definition
(from proj or wkt), instead of requiring them to add a custom
CRS to their database.

It's much friendlier for users who just want to defined a custom
projection for e.g. an overview map.
  • Loading branch information
nyalldawson committed Jan 11, 2022
1 parent 0ad1324 commit d8de54387256cd20dfd51d583324d1f310cc65a2
@@ -105,6 +105,13 @@ Sets the dialog to require a valid selection only, preventing users from accepti
dialog if no selection is present.

.. versionadded:: 3.18
%End

bool hasValidSelection() const;
%Docstring
Returns ``True`` if the dialog has a valid CRS defined.

.. versionadded:: 3.24
%End

public slots:
@@ -35,6 +35,29 @@ QgsProjectionSelectionDialog::QgsProjectionSelectionDialog( QWidget *parent,
//we will show this only when a message is set
textEdit->hide();

tabWidget->setCurrentWidget( mTabDatabase );

mCheckBoxNoProjection->setHidden( true );
mCheckBoxNoProjection->setEnabled( false );
connect( mCheckBoxNoProjection, &QCheckBox::toggled, this, [ = ]
{
#if 0
if ( !mBlockSignals )
{
emit crsSelected();
emit hasValidSelectionChanged( hasValidSelection() );
}
#endif
} );
connect( mCheckBoxNoProjection, &QCheckBox::toggled, this, [ = ]( bool checked )
{
if ( mCheckBoxNoProjection->isEnabled() )
{
tabWidget->setDisabled( checked );
}
} );


//apply selected projection upon double-click on item
connect( projectionSelector, &QgsProjectionSelectionTreeWidget::projectionDoubleClicked, this, &QgsProjectionSelectionDialog::accept );

@@ -65,37 +88,94 @@ void QgsProjectionSelectionDialog::showNoCrsForLayerMessage()

void QgsProjectionSelectionDialog::setShowNoProjection( bool show )
{
projectionSelector->setShowNoProjection( show );
mCheckBoxNoProjection->setVisible( show );
mCheckBoxNoProjection->setEnabled( show );
if ( show )
{
tabWidget->setDisabled( mCheckBoxNoProjection->isChecked() );
}

if ( mRequireValidSelection )
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( hasValidSelection() );
}

bool QgsProjectionSelectionDialog::showNoProjection() const
{
return projectionSelector->showNoProjection();
return !mCheckBoxNoProjection->isHidden();
}

void QgsProjectionSelectionDialog::setNotSetText( const QString &text )
{
projectionSelector->setNotSetText( text );
mCheckBoxNoProjection->setText( text );
}

void QgsProjectionSelectionDialog::setRequireValidSelection()
{
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( projectionSelector->hasValidSelection() );
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( hasValidSelection() );

connect( projectionSelector, &QgsProjectionSelectionTreeWidget::hasValidSelectionChanged, this, [ = ]( bool )
{
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( hasValidSelection() );
} );

connect( projectionSelector, &QgsProjectionSelectionTreeWidget::hasValidSelectionChanged, this, [ = ]( bool isValid )
connect( mCheckBoxNoProjection, &QCheckBox::toggled, this, [ = ]( bool )
{
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( isValid );
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( hasValidSelection() );
} );

connect( mCrsDefinitionWidget, &QgsCrsDefinitionWidget::crsChanged, this, [ = ]()
{
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( hasValidSelection() );
} );

connect( tabWidget, &QTabWidget::currentChanged, this, [ = ]()
{
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( hasValidSelection() );
} );
}

bool QgsProjectionSelectionDialog::hasValidSelection() const
{
if ( mCheckBoxNoProjection->isChecked() )
return true;

if ( tabWidget->currentWidget() == mTabCustom )
return mCrsDefinitionWidget->crs().isValid();
else
return projectionSelector->hasValidSelection();
}

QgsCoordinateReferenceSystem QgsProjectionSelectionDialog::crs() const
{
return projectionSelector->crs();
if ( mCheckBoxNoProjection->isEnabled() && mCheckBoxNoProjection->isChecked() )
return QgsCoordinateReferenceSystem();

if ( tabWidget->currentWidget() == mTabCustom )
return mCrsDefinitionWidget->crs();
else
return projectionSelector->crs();
}

void QgsProjectionSelectionDialog::setCrs( const QgsCoordinateReferenceSystem &crs )
{
projectionSelector->setCrs( crs );
if ( !crs.isValid() )
{
mCheckBoxNoProjection->setChecked( true );
}
else
{
mCheckBoxNoProjection->setChecked( false );

projectionSelector->setCrs( crs );
mCrsDefinitionWidget->setCrs( crs );
if ( crs.isValid() && crs.authid().isEmpty() )
tabWidget->setCurrentWidget( mTabCustom );
else
tabWidget->setCurrentWidget( mTabDatabase );
}

if ( mRequireValidSelection )
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( hasValidSelection() );
}

void QgsProjectionSelectionDialog::setOgcWmsCrsFilter( const QSet<QString> &crsFilter )
@@ -114,6 +114,13 @@ class GUI_EXPORT QgsProjectionSelectionDialog : public QDialog, private Ui::QgsG
*/
void setRequireValidSelection();

/**
* Returns TRUE if the dialog has a valid CRS defined.
*
* \since QGIS 3.24
*/
bool hasValidSelection() const;

public slots:

/**
@@ -140,6 +147,10 @@ class GUI_EXPORT QgsProjectionSelectionDialog : public QDialog, private Ui::QgsG
private slots:

void showHelp();

private:

bool mRequireValidSelection = false;
};

#endif // #ifndef QGSLAYERCRSSELECTOR_H
@@ -20,42 +20,76 @@
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QSplitter" name="mSplitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
<widget class="QCheckBox" name="mCheckBoxNoProjection">
<property name="toolTip">
<string>Use this option to treat all coordinates as Cartesian coordinates in an unknown reference system.</string>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
<property name="text">
<string>No CRS (or unknown/non-Earth projection)</string>
</property>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QTextEdit" name="textEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>160</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="lineWidth">
<number>2</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<widget class="QWidget" name="mTabDatabase">
<attribute name="title">
<string>CRS Database</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QSplitter" name="mSplitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QTextEdit" name="textEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>160</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="acceptDrops">
<bool>false</bool>
</property>
<property name="lineWidth">
<number>2</number>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<widget class="QgsProjectionSelectionTreeWidget" name="projectionSelector" native="true"/>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mTabCustom">
<attribute name="title">
<string>Custom CRS</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QgsCrsDefinitionWidget" name="mCrsDefinitionWidget" native="true"/>
</item>
</layout>
</widget>
<widget class="QgsProjectionSelectionTreeWidget" name="projectionSelector" native="true"/>
</widget>
</item>
<item>
@@ -72,6 +106,12 @@
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QgsCrsDefinitionWidget</class>
<extends>QWidget</extends>
<header>qgscrsdefinitionwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsProjectionSelectionTreeWidget</class>
<extends>QWidget</extends>

0 comments on commit d8de543

Please sign in to comment.