Skip to content

Commit

Permalink
[needs-docs] Rework new project CRS handling
Browse files Browse the repository at this point in the history
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

(cherry picked from commit dac7259)
  • Loading branch information
nyalldawson committed Jun 3, 2019
1 parent 768a8da commit 72628b9
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 76 deletions.
2 changes: 2 additions & 0 deletions python/gui/auto_additions/qgsgui.py
@@ -0,0 +1,2 @@
# The following has been generated automatically from src/gui/qgsgui.h
QgsGui.ProjectCrsBehavior.baseClass = QgsGui
8 changes: 7 additions & 1 deletion python/gui/auto_generated/qgsgui.sip.in
Expand Up @@ -10,7 +10,7 @@



class QgsGui
class QgsGui : QObject
{
%Docstring
QgsGui is a singleton class containing various registry and other global members
Expand All @@ -24,6 +24,12 @@ related to GUI classes.
%End
public:

enum ProjectCrsBehavior
{
UseCrsOfFirstLayerAdded,
UsePresetCrs,
};



static QgsGui *instance();
Expand Down
18 changes: 18 additions & 0 deletions resources/qgis_global_settings.ini
Expand Up @@ -54,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
Expand Down Expand Up @@ -91,3 +107,5 @@ default_checks=
# Enable problem resolution for geometry errors
# This feature is experimental and has known issues.
enable_problem_resolution=false


3 changes: 1 addition & 2 deletions src/app/qgisapp.cpp
Expand Up @@ -5436,8 +5436,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() );
Expand Down
1 change: 1 addition & 0 deletions src/app/qgisapp.h
Expand Up @@ -173,6 +173,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(),
Expand Down
30 changes: 18 additions & 12 deletions src/app/qgsoptions.cpp
Expand Up @@ -51,6 +51,7 @@
#include "qgsoptionswidgetfactory.h"
#include "qgslocatorwidget.h"
#include "qgslocatoroptionswidget.h"
#include "qgsgui.h"

#ifdef HAVE_OPENCL
#include "qgsopenclutils.h"
Expand Down Expand Up @@ -89,7 +90,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 );
Expand Down Expand Up @@ -460,12 +460,22 @@ 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/showDatumTransformDialog" ), false ).toBool() );
mShowDatumTransformDialogCheckBox->setChecked( mSettings->value( QStringLiteral( "/projections/promptWhenMultipleTransformsExist" ), false, QgsSettings::App ).toBool() );

// Datum transforms
QgsCoordinateTransformContext context;
Expand Down Expand Up @@ -1533,9 +1543,9 @@ void QgsOptions::saveOptions()
}

mSettings->setValue( QStringLiteral( "/Projections/layerDefaultCrs" ), mLayerDefaultCrs.authid() );
mSettings->setValue( QStringLiteral( "/Projections/projectDefaultCrs" ), mDefaultCrs.authid() );

mSettings->setValue( QStringLiteral( "/Projections/showDatumTransformDialog" ), mShowDatumTransformDialogCheckBox->isChecked() );
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

Expand Down Expand Up @@ -1783,10 +1793,6 @@ void QgsOptions::mFontFamilyComboBox_currentFontChanged( const QFont &font )
}
}

void QgsOptions::leProjectGlobalCrs_crsChanged( const QgsCoordinateReferenceSystem &crs )
{
mDefaultCrs = crs;
}

void QgsOptions::leLayerGlobalCrs_crsChanged( const QgsCoordinateReferenceSystem &crs )
{
Expand Down
3 changes: 0 additions & 3 deletions src/app/qgsoptions.h
Expand Up @@ -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 );
Expand Down Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion src/gui/CMakeLists.txt
Expand Up @@ -454,6 +454,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsgradientcolorrampdialog.h
qgsgradientstopeditor.h
qgsgroupwmsdatadialog.h
qgsgui.h
qgshistogramwidget.h
qgshighlight.h
qgsidentifymenu.h
Expand Down Expand Up @@ -770,7 +771,6 @@ SET(QGIS_GUI_HDRS
qgsdetaileditemdata.h
qgsexpressionbuilderdialog.h
qgsgeometryrubberband.h
qgsgui.h
qgsguiutils.h
qgshelp.h
qgshighlight.h
Expand Down
13 changes: 12 additions & 1 deletion src/gui/layertree/qgslayertreemapcanvasbridge.cpp
Expand Up @@ -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 )
Expand Down Expand Up @@ -98,7 +100,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;
}
}

mLastLayerCount = currentSpatialLayerCount;
Expand Down
14 changes: 13 additions & 1 deletion src/gui/qgsgui.h
Expand Up @@ -41,10 +41,22 @@ class QgsWindowManagerInterface;
* 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;

Expand Down
3 changes: 1 addition & 2 deletions src/gui/qgsprojectionselectionwidget.cpp
Expand Up @@ -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
Expand Down

0 comments on commit 72628b9

Please sign in to comment.