[needs-docs] Rework new project CRS handling

The previous approach was severely broken, because the default
CRS for new projects setting was ignored as soon as a layer
was added to the project.

Instead, refine the setting to add options
- "Use CRS from first layer added": same as previous behavior,
the project CRS is set to match the first layer added to a new
project
- "Use a default CRS": CRS for a new project is set to a preset
default CRS, and is left unchanged when adding layers to the
project

Also update qgis_global_settings.ini to reflect these changes.

Fixes #27516
This commit is contained in:
Nyall Dawson 2019-05-28 09:46:32 +10:00
parent 10c686ba32
commit dac7259b46
12 changed files with 174 additions and 102 deletions

View File

@ -0,0 +1,2 @@
# The following has been generated automatically from src/gui/qgsgui.h
QgsGui.ProjectCrsBehavior.baseClass = QgsGui

View File

@ -10,7 +10,7 @@
class QgsGui
class QgsGui : QObject
{
%Docstring
QgsGui is a singleton class containing various registry and other global members
@ -24,6 +24,12 @@ related to GUI classes.
%End
public:
enum ProjectCrsBehavior
{
UseCrsOfFirstLayerAdded,
UsePresetCrs,
};
static QgsGui *instance();

View File

@ -40,11 +40,6 @@ connections-xyz\OpenStreetMap\username=
connections-xyz\OpenStreetMap\zmax=19
connections-xyz\OpenStreetMap\zmin=0
# Whether to prompt users for a selection when multiple possible transformation paths exist
# when transforming coordinates. If false, a reasonable choice will be estimated by default
# without asking users. If true, users are always required to make this choice themselves.
projections\promptWhenMultipleTransformsExist=false
# application stylesheet
# Padding (in pixels) to add to toolbar icons, if blank then default padding will be used
@ -59,6 +54,22 @@ maxRecentProjects=20
# notification to be shown when the task completes.
minTaskLengthForSystemNotification=5
# Whether to prompt users for a selection when multiple possible transformation paths exist
# when transforming coordinates. If false, a reasonable choice will be estimated by default
# without asking users. If true, users are always required to make this choice themselves.
projections\promptWhenMultipleTransformsExist=true
# Default CRS for newly created projects. Accepts "auth:code" style strings (e.g. EPSG:4326),
# PROJ strings (must be prefixed with PROJ4:, e.g. "PROJ4:+proj ...."), or WKT strings (must
# be prefixed with WKT:, e.g. "WKT:<wkt string>")
# This is only used when projections\newProjectCrsBehavior is set to UsePresetCrs
projections\defaultProjectCrs=EPSG:4326
# Specifies the method to set the CRS for a newly created project. Valid options are
# "UseCrsOfFirstLayerAdded" - sets the project CRS to match the CRS of the first layer added to the project
# "UsePresetCrs" - always use a preset CRS, see projections\defaultProjectCrs
projections\newProjectCrsBehavior=UseCrsOfFirstLayerAdded
[core]
# Whether or not to anonymize newly created projects
# If set to 1, then project metadata items like AUTHOR and CREATION DATE
@ -96,3 +107,5 @@ default_checks=
# Enable problem resolution for geometry errors
# This feature is experimental and has known issues.
enable_problem_resolution=false

View File

@ -5495,8 +5495,7 @@ bool QgisApp::fileNew( bool promptToSaveFlag, bool forceBlank )
mScaleWidget->updateScales();
// set project CRS
QString defCrs = settings.value( QStringLiteral( "Projections/projectDefaultCrs" ), GEO_EPSG_CRS_AUTHID ).toString();
QgsCoordinateReferenceSystem srs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( defCrs );
const QgsCoordinateReferenceSystem srs = QgsCoordinateReferenceSystem( settings.value( QStringLiteral( "/projections/defaultProjectCrs" ), GEO_EPSG_CRS_AUTHID, QgsSettings::App ).toString() );
// write the projections _proj string_ to project settings
prj->setCrs( srs );
prj->setEllipsoid( srs.ellipsoidAcronym() );

View File

@ -177,6 +177,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
{
Q_OBJECT
public:
//! Constructor
QgisApp( QSplashScreen *splash, bool restorePlugins = true,
bool skipVersionCheck = false, const QString &rootProfileLocation = QString(),

View File

@ -52,6 +52,7 @@
#include "qgsoptionswidgetfactory.h"
#include "qgslocatorwidget.h"
#include "qgslocatoroptionswidget.h"
#include "qgsgui.h"
#ifdef HAVE_OPENCL
#include "qgsopenclutils.h"
@ -90,7 +91,6 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
{
setupUi( this );
connect( cbxProjectDefaultNew, &QCheckBox::toggled, this, &QgsOptions::cbxProjectDefaultNew_toggled );
connect( leProjectGlobalCrs, &QgsProjectionSelectionWidget::crsChanged, this, &QgsOptions::leProjectGlobalCrs_crsChanged );
connect( leLayerGlobalCrs, &QgsProjectionSelectionWidget::crsChanged, this, &QgsOptions::leLayerGlobalCrs_crsChanged );
connect( lstGdalDrivers, &QTreeWidget::itemDoubleClicked, this, &QgsOptions::lstGdalDrivers_itemDoubleClicked );
connect( mProjectOnLaunchCmbBx, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsOptions::mProjectOnLaunchCmbBx_currentIndexChanged );
@ -444,7 +444,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
// log rendering events, for userspace debugging
mLogCanvasRefreshChkBx->setChecked( mSettings->value( QStringLiteral( "/Map/logCanvasRefreshEvent" ), false ).toBool() );
//set the default projection behavior radio buttongs
//set the default projection behavior radio buttons
if ( mSettings->value( QStringLiteral( "/Projections/defaultBehavior" ), "prompt" ).toString() == QLatin1String( "prompt" ) )
{
radPromptForProjection->setChecked( true );
@ -461,10 +461,20 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
mLayerDefaultCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( myLayerDefaultCrs );
leLayerGlobalCrs->setCrs( mLayerDefaultCrs );
QString myDefaultCrs = mSettings->value( QStringLiteral( "/Projections/projectDefaultCrs" ), GEO_EPSG_CRS_AUTHID ).toString();
mDefaultCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( myDefaultCrs );
leProjectGlobalCrs->setCrs( mDefaultCrs );
const QString defaultProjectCrs = mSettings->value( QStringLiteral( "/projections/defaultProjectCrs" ), GEO_EPSG_CRS_AUTHID, QgsSettings::App ).toString();
leProjectGlobalCrs->setCrs( QgsCoordinateReferenceSystem( defaultProjectCrs ) );
leProjectGlobalCrs->setOptionVisible( QgsProjectionSelectionWidget::DefaultCrs, false );
const QgsGui::ProjectCrsBehavior projectCrsBehavior = mSettings->enumValue( QStringLiteral( "/projections/newProjectCrsBehavior" ), QgsGui::UseCrsOfFirstLayerAdded, QgsSettings::App );
switch ( projectCrsBehavior )
{
case QgsGui::UseCrsOfFirstLayerAdded:
radProjectUseCrsOfFirstLayer->setChecked( true );
break;
case QgsGui::UsePresetCrs:
radProjectUseDefaultCrs->setChecked( true );
break;
}
mShowDatumTransformDialogCheckBox->setChecked( mSettings->value( QStringLiteral( "/projections/promptWhenMultipleTransformsExist" ), false, QgsSettings::App ).toBool() );
@ -1539,8 +1549,8 @@ void QgsOptions::saveOptions()
}
mSettings->setValue( QStringLiteral( "/Projections/layerDefaultCrs" ), mLayerDefaultCrs.authid() );
mSettings->setValue( QStringLiteral( "/Projections/projectDefaultCrs" ), mDefaultCrs.authid() );
mSettings->setValue( QStringLiteral( "/projections/defaultProjectCrs" ), leProjectGlobalCrs->crs().authid(), QgsSettings::App );
mSettings->setEnumValue( QStringLiteral( "/projections/newProjectCrsBehavior" ), radProjectUseCrsOfFirstLayer->isChecked() ? QgsGui::UseCrsOfFirstLayerAdded : QgsGui::UsePresetCrs, QgsSettings::App );
mSettings->setValue( QStringLiteral( "/projections/promptWhenMultipleTransformsExist" ), mShowDatumTransformDialogCheckBox->isChecked(), QgsSettings::App );
//measurement settings
@ -1784,11 +1794,6 @@ void QgsOptions::mFontFamilyComboBox_currentFontChanged( const QFont &font )
}
}
void QgsOptions::leProjectGlobalCrs_crsChanged( const QgsCoordinateReferenceSystem &crs )
{
mDefaultCrs = crs;
}
void QgsOptions::leLayerGlobalCrs_crsChanged( const QgsCoordinateReferenceSystem &crs )
{
mLayerDefaultCrs = crs;

View File

@ -69,8 +69,6 @@ class APP_EXPORT QgsOptions : public QgsOptionsDialogBase, private Ui::QgsOption
void resetProjectDefault();
void browseTemplateFolder();
void resetTemplateFolder();
//! Slot called when user chooses to change the project wide projection.
void leProjectGlobalCrs_crsChanged( const QgsCoordinateReferenceSystem &crs );
//! Slot called when user chooses to change the default 'on the fly' projection.
void leLayerGlobalCrs_crsChanged( const QgsCoordinateReferenceSystem &crs );
void lstGdalDrivers_itemDoubleClicked( QTreeWidgetItem *item, int column );
@ -237,7 +235,6 @@ class APP_EXPORT QgsOptions : public QgsOptionsDialogBase, private Ui::QgsOption
void saveMinMaxLimits( QComboBox *cbox, const QString &name );
void setZoomFactorValue();
double zoomFactorValue();
QgsCoordinateReferenceSystem mDefaultCrs;
QgsCoordinateReferenceSystem mLayerDefaultCrs;
bool mLoadedGdalDriverList;

View File

@ -469,6 +469,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsgradientcolorrampdialog.h
qgsgradientstopeditor.h
qgsgroupwmsdatadialog.h
qgsgui.h
qgshistogramwidget.h
qgshighlight.h
qgsidentifymenu.h
@ -791,7 +792,6 @@ SET(QGIS_GUI_HDRS
qgsdetaileditemdata.h
qgsexpressionbuilderdialog.h
qgsgeometryrubberband.h
qgsgui.h
qgsguiutils.h
qgshelp.h
qgshighlight.h

View File

@ -22,6 +22,8 @@
#include "qgsmapcanvas.h"
#include "qgsmapoverviewcanvas.h"
#include "qgsproject.h"
#include "qgssettings.h"
#include "qgsgui.h"
QgsLayerTreeMapCanvasBridge::QgsLayerTreeMapCanvasBridge( QgsLayerTree *root, QgsMapCanvas *canvas, QObject *parent )
: QObject( parent )
@ -101,7 +103,16 @@ void QgsLayerTreeMapCanvasBridge::setCanvasLayers()
if ( mFirstCRS.isValid() && firstLayers )
{
QgsProject::instance()->setCrs( mFirstCRS );
const QgsGui::ProjectCrsBehavior projectCrsBehavior = QgsSettings().enumValue( QStringLiteral( "/projections/newProjectCrsBehavior" ), QgsGui::UseCrsOfFirstLayerAdded, QgsSettings::App );
switch ( projectCrsBehavior )
{
case QgsGui::UseCrsOfFirstLayerAdded:
QgsProject::instance()->setCrs( mFirstCRS );
break;
case QgsGui::UsePresetCrs:
break;
}
}
mHasLayersLoaded = currentSpatialLayerCount;

View File

@ -42,10 +42,22 @@ class QgsDataItemGuiProviderRegistry;
* related to GUI classes.
* \since QGIS 3.0
*/
class GUI_EXPORT QgsGui
class GUI_EXPORT QgsGui : public QObject
{
Q_OBJECT
public:
/**
* Defines the behavior to use when setting the CRS for a newly created project.
*/
enum ProjectCrsBehavior
{
UseCrsOfFirstLayerAdded = 1, //!< Set the project CRS to the CRS of the first layer added to a new project
UsePresetCrs = 2, //!< Always set new projects to use a preset default CRS
};
Q_ENUM( ProjectCrsBehavior )
//! QgsGui cannot be copied
QgsGui( const QgsGui &other ) = delete;

View File

@ -39,8 +39,7 @@ QgsProjectionSelectionWidget::QgsProjectionSelectionWidget( QWidget *parent )
addProjectCrsOption();
QgsSettings settings;
QString defCrsString = settings.value( QStringLiteral( "Projections/projectDefaultCrs" ), GEO_EPSG_CRS_AUTHID ).toString();
mDefaultCrs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( defCrsString );
mDefaultCrs = QgsCoordinateReferenceSystem( settings.value( QStringLiteral( "/projections/defaultProjectCrs" ), GEO_EPSG_CRS_AUTHID, QgsSettings::App ).toString() );
if ( mDefaultCrs.authid() != mProjectCrs.authid() )
{
//only show default CRS option if it's different to the project CRS, avoids

View File

@ -1626,10 +1626,108 @@
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_15">
<item row="2" column="0">
<widget class="QgsCollapsibleGroupBox" name="grpProjectProjection">
<property name="title">
<string>CRS for New Projects</string>
</property>
<layout class="QGridLayout" name="gridLayout_27" columnstretch="0,1">
<item row="0" column="0" colspan="2">
<widget class="QLabel" name="label_42">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>When a new project is created</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QgsProjectionSelectionWidget" name="leProjectGlobalCrs" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>5</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="radProjectUseDefaultCrs">
<property name="text">
<string>&amp;Use a default CRS</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QRadioButton" name="radProjectUseCrsOfFirstLayer">
<property name="text">
<string>Use CRS from first layer added</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0">
<widget class="QgsCollapsibleGroupBox" name="mDefaultDatumTransformGroupBox">
<property name="title">
<string>Default Datum Transformations</string>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<item row="2" column="0">
<widget class="QLabel" name="label_40">
<property name="text">
<string>Enter default datum transformations which will be used in any newly created project</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mShowDatumTransformDialogCheckBox">
<property name="text">
<string>Ask for datum transformation if several are available</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QgsDatumTransformTableWidget" name="mDefaultDatumTransformTableWidget" native="true"/>
</item>
</layout>
</widget>
</item>
<item row="5" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<widget class="QgsCollapsibleGroupBox" name="grpProjectionBehavior">
<property name="title">
<string>CRS for new layers</string>
<string>CRS for New Layers</string>
</property>
<layout class="QGridLayout" name="gridLayout_14" columnstretch="0,1">
<item row="0" column="0" colspan="2">
@ -1682,79 +1780,6 @@
</layout>
</widget>
</item>
<item row="5" column="0">
<widget class="QgsCollapsibleGroupBox" name="mDefaultDatumTransformGroupBox">
<property name="title">
<string>Default datum transformations</string>
</property>
<layout class="QGridLayout" name="gridLayout_10">
<item row="2" column="0">
<widget class="QLabel" name="label_40">
<property name="text">
<string>Enter default datum transformations which will be used in any newly created project</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="mShowDatumTransformDialogCheckBox">
<property name="text">
<string>Ask for datum transformation if several are available</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QgsDatumTransformTableWidget" name="mDefaultDatumTransformTableWidget" native="true"/>
</item>
</layout>
</widget>
</item>
<item row="6" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="0,1">
<property name="topMargin">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label_16">
<property name="text">
<string>Default CRS for new projects</string>
</property>
</widget>
</item>
<item>
<widget class="QgsProjectionSelectionWidget" name="leProjectGlobalCrs" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>5</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
@ -5581,6 +5606,8 @@ p, li { white-space: pre-wrap; }
<tabstop>mCurrentVariablesTable</tabstop>
<tabstop>mCurrentVariablesQGISChxBx</tabstop>
<tabstop>mOptionsScrollArea_08</tabstop>
<tabstop>radProjectUseCrsOfFirstLayer</tabstop>
<tabstop>radProjectUseDefaultCrs</tabstop>
<tabstop>leProjectGlobalCrs</tabstop>
<tabstop>radPromptForProjection</tabstop>
<tabstop>radUseProjectProjection</tabstop>