Skip to content

Commit

Permalink
Move custom projections dialog to a tab in the main settings dialog
Browse files Browse the repository at this point in the history
Avoids an isolated settings dialog and helps consolidate all settings
in the one place.

For now the top-level Custom Projections menu action remains
and just opens the options dialog at the corresponding page, but
in a few releases time (or in 4.0) we could safely remove this.
  • Loading branch information
nyalldawson committed Jan 14, 2022
1 parent f288ab1 commit e8f427a
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 103 deletions.
2 changes: 1 addition & 1 deletion src/app/CMakeLists.txt
Expand Up @@ -26,7 +26,6 @@ set(QGIS_APP_SRCS
qgsbookmarkeditordialog.cpp
qgsclipboard.cpp
qgscustomization.cpp
qgscustomprojectiondialog.cpp
qgsdatumtransformtablewidget.cpp
qgsdevtoolspanelwidget.cpp
qgsdiscoverrelationsdialog.cpp
Expand Down Expand Up @@ -228,6 +227,7 @@ set(QGIS_APP_SRCS

options/qgsadvancedoptions.cpp
options/qgscodeeditoroptions.cpp
options/qgscustomprojectionoptions.cpp
options/qgsgpsdeviceoptions.cpp
options/qgsoptions.cpp
options/qgsoptionsutils.cpp
Expand Down
@@ -1,5 +1,5 @@
/***************************************************************************
qgscustomprojectiondialog.cpp
qgscustomprojectionoptions.cpp
-------------------
begin : 2005
Expand All @@ -16,43 +16,30 @@
* *
***************************************************************************/

#include "qgscustomprojectiondialog.h"

//qgis includes
#include "qgis.h" //<--magick numbers
#include "qgisapp.h" //<--theme icons
#include "qgscustomprojectionoptions.h"
#include "qgsapplication.h"
#include "qgslogger.h"
#include "qgsprojectionselectiondialog.h"
#include "qgssettings.h"
#include "qgsgui.h"
#include "qgscoordinatereferencesystemregistry.h"

//qt includes
#include <QFileInfo>
#include <QMessageBox>
#include <QLocale>
#include <QRegularExpression>
#include <QFileInfo>

QgsCustomProjectionDialog::QgsCustomProjectionDialog( QWidget *parent, Qt::WindowFlags fl )
: QDialog( parent, fl )
QgsCustomProjectionOptionsWidget::QgsCustomProjectionOptionsWidget( QWidget *parent )
: QgsOptionsPageWidget( parent )
{
setupUi( this );
QgsGui::enableAutoGeometryRestore( this );
setObjectName( QStringLiteral( "QgsCustomProjectionOptionsWidget" ) );

connect( pbnAdd, &QPushButton::clicked, this, &QgsCustomProjectionDialog::pbnAdd_clicked );
connect( pbnRemove, &QPushButton::clicked, this, &QgsCustomProjectionDialog::pbnRemove_clicked );
connect( leNameList, &QTreeWidget::currentItemChanged, this, &QgsCustomProjectionDialog::leNameList_currentItemChanged );
connect( buttonBox, &QDialogButtonBox::accepted, this, &QgsCustomProjectionDialog::buttonBox_accepted );
connect( buttonBox, &QDialogButtonBox::helpRequested, this, &QgsCustomProjectionDialog::showHelp );
connect( pbnAdd, &QPushButton::clicked, this, &QgsCustomProjectionOptionsWidget::pbnAdd_clicked );
connect( pbnRemove, &QPushButton::clicked, this, &QgsCustomProjectionOptionsWidget::pbnRemove_clicked );
connect( leNameList, &QTreeWidget::currentItemChanged, this, &QgsCustomProjectionOptionsWidget::leNameList_currentItemChanged );

leNameList->setSelectionMode( QAbstractItemView::ExtendedSelection );

// user database is created at QGIS startup in QgisApp::createDB
// we just check whether there is our database [MD]
QFileInfo fileInfo;
fileInfo.setFile( QgsApplication::qgisSettingsDirPath() );
if ( !fileInfo.exists() )
if ( !QFileInfo::exists( QgsApplication::qgisSettingsDirPath() ) )
{
QgsDebugMsg( QStringLiteral( "The qgis.db does not exist" ) );
}
Expand All @@ -72,7 +59,7 @@ QgsCustomProjectionDialog::QgsCustomProjectionDialog( QWidget *parent, Qt::Windo

QgsCoordinateReferenceSystem crs;
Qgis::CrsDefinitionFormat format;
if ( mDefinitions[0].wkt.isEmpty() )
if ( mDefinitions.at( 0 ).wkt.isEmpty() )
{
crs.createFromProj( mDefinitions[0].proj );
format = Qgis::CrsDefinitionFormat::Proj;
Expand All @@ -90,15 +77,15 @@ QgsCustomProjectionDialog::QgsCustomProjectionDialog( QWidget *parent, Qt::Windo

leNameList->hideColumn( QgisCrsIdColumn );

connect( leName, &QLineEdit::textChanged, this, &QgsCustomProjectionDialog::updateListFromCurrentItem );
connect( leName, &QLineEdit::textChanged, this, &QgsCustomProjectionOptionsWidget::updateListFromCurrentItem );
connect( mCrsDefinitionWidget, &QgsCrsDefinitionWidget::crsChanged, this, [ = ]
{
if ( !mBlockUpdates )
updateListFromCurrentItem();
} );
}

void QgsCustomProjectionDialog::populateList()
void QgsCustomProjectionOptionsWidget::populateList()
{
const QList< QgsCoordinateReferenceSystemRegistry::UserCrsDetails > userCrsList = QgsApplication::coordinateReferenceSystemRegistry()->userCrsList();

Expand Down Expand Up @@ -136,7 +123,7 @@ void QgsCustomProjectionDialog::populateList()
}
}

bool QgsCustomProjectionDialog::saveCrs( QgsCoordinateReferenceSystem crs, const QString &name, const QString &existingId, bool newEntry, Qgis::CrsDefinitionFormat format )
bool QgsCustomProjectionOptionsWidget::saveCrs( const QgsCoordinateReferenceSystem &crs, const QString &name, const QString &existingId, bool newEntry, Qgis::CrsDefinitionFormat format )
{
QString id = existingId;
if ( newEntry )
Expand All @@ -162,7 +149,7 @@ bool QgsCustomProjectionDialog::saveCrs( QgsCoordinateReferenceSystem crs, const
return true;
}

void QgsCustomProjectionDialog::pbnAdd_clicked()
void QgsCustomProjectionOptionsWidget::pbnAdd_clicked()
{
QString name = tr( "new CRS" );

Expand All @@ -183,7 +170,7 @@ void QgsCustomProjectionDialog::pbnAdd_clicked()
mCrsDefinitionWidget->setFormat( Qgis::CrsDefinitionFormat::Wkt );
}

void QgsCustomProjectionDialog::pbnRemove_clicked()
void QgsCustomProjectionOptionsWidget::pbnRemove_clicked()
{
const QModelIndexList selection = leNameList->selectionModel()->selectedRows();
if ( selection.empty() )
Expand Down Expand Up @@ -218,7 +205,7 @@ void QgsCustomProjectionDialog::pbnRemove_clicked()
}
}

void QgsCustomProjectionDialog::leNameList_currentItemChanged( QTreeWidgetItem *current, QTreeWidgetItem *previous )
void QgsCustomProjectionOptionsWidget::leNameList_currentItemChanged( QTreeWidgetItem *current, QTreeWidgetItem *previous )
{
//Store the modifications made to the current element before moving on
int currentIndex, previousIndex;
Expand Down Expand Up @@ -252,7 +239,7 @@ void QgsCustomProjectionDialog::leNameList_currentItemChanged( QTreeWidgetItem *

mBlockUpdates++;
mCrsDefinitionWidget->setDefinitionString( !mDefinitions[currentIndex].wkt.isEmpty() ? current->data( 0, FormattedWktRole ).toString() : mDefinitions[currentIndex].proj );
mCrsDefinitionWidget->setFormat( mDefinitions[currentIndex].wkt.isEmpty() ? Qgis::CrsDefinitionFormat::Proj : Qgis::CrsDefinitionFormat::Wkt );
mCrsDefinitionWidget->setFormat( mDefinitions.at( currentIndex ).wkt.isEmpty() ? Qgis::CrsDefinitionFormat::Proj : Qgis::CrsDefinitionFormat::Wkt );
mBlockUpdates--;
}
else
Expand All @@ -267,12 +254,10 @@ void QgsCustomProjectionDialog::leNameList_currentItemChanged( QTreeWidgetItem *
}
}

void QgsCustomProjectionDialog::buttonBox_accepted()
bool QgsCustomProjectionOptionsWidget::isValid()
{
updateListFromCurrentItem();

QgsDebugMsgLevel( QStringLiteral( "We save the modified CRS." ), 4 );

//Check if all CRS are valid:
QgsCoordinateReferenceSystem crs;
for ( const Definition &def : std::as_const( mDefinitions ) )
Expand All @@ -296,7 +281,7 @@ void QgsCustomProjectionDialog::buttonBox_accepted()

QMessageBox::warning( this, tr( "Custom Coordinate Reference System" ),
tr( "The definition of '%1' is not valid." ).arg( def.name ) );
return;
return false;
}
else if ( !crs.authid().isEmpty() && !crs.authid().startsWith( QLatin1String( "USER" ), Qt::CaseInsensitive ) )
{
Expand Down Expand Up @@ -334,12 +319,19 @@ void QgsCustomProjectionDialog::buttonBox_accepted()
tr( "Cannot save '%1' — the definition is equivalent to %2." ).arg( def.name, crs.authid() ) );
}
}
return;
return false;
}
}
return true;
}

void QgsCustomProjectionOptionsWidget::apply()
{
// note that isValid() will have already been called prior to this, so we don't need to re-validate!

//Modify the CRS changed:
bool saveSuccess = true;
QgsCoordinateReferenceSystem crs;
for ( const Definition &def : std::as_const( mDefinitions ) )
{
if ( !def.wkt.isEmpty() )
Expand Down Expand Up @@ -373,16 +365,12 @@ void QgsCustomProjectionDialog::buttonBox_accepted()
saveSuccess &= QgsApplication::coordinateReferenceSystemRegistry()->removeUserCrs( mDeletedCRSs[i].toLong() );
if ( ! saveSuccess )
{
QgsDebugMsg( QStringLiteral( "Error deleting CRS for '%1'" ).arg( mDefinitions[i].name ) );
QgsDebugMsg( QStringLiteral( "Error deleting CRS for '%1'" ).arg( mDefinitions.at( i ).name ) );
}
}
if ( saveSuccess )
{
accept();
}
}

void QgsCustomProjectionDialog::updateListFromCurrentItem()
void QgsCustomProjectionOptionsWidget::updateListFromCurrentItem()
{
QTreeWidgetItem *item = leNameList->currentItem();
if ( !item )
Expand Down Expand Up @@ -411,12 +399,7 @@ void QgsCustomProjectionDialog::updateListFromCurrentItem()
item->setData( 0, FormattedWktRole, mCrsDefinitionWidget->definitionString() );
}

void QgsCustomProjectionDialog::showHelp()
{
QgsHelp::openHelp( QStringLiteral( "working_with_projections/working_with_projections.html" ) );
}

QString QgsCustomProjectionDialog::multiLineWktToSingleLine( const QString &wkt )
QString QgsCustomProjectionOptionsWidget::multiLineWktToSingleLine( const QString &wkt )
{
QString res = wkt;
QRegularExpression re( QStringLiteral( "\\s*\\n\\s*" ) );
Expand All @@ -425,3 +408,33 @@ QString QgsCustomProjectionDialog::multiLineWktToSingleLine( const QString &wkt
return res;
}

QString QgsCustomProjectionOptionsWidget::helpKey() const
{
return QStringLiteral( "working_with_projections/working_with_projections.html" );
}


//
// QgsCustomProjectionOptionsFactory
//
QgsCustomProjectionOptionsFactory::QgsCustomProjectionOptionsFactory()
: QgsOptionsWidgetFactory( tr( "Custom Projections" ), QIcon() )
{

}

QIcon QgsCustomProjectionOptionsFactory::icon() const
{
return QgsApplication::getThemeIcon( QStringLiteral( "mActionCustomProjection.svg" ) );
}

QgsOptionsPageWidget *QgsCustomProjectionOptionsFactory::createWidget( QWidget *parent ) const
{
return new QgsCustomProjectionOptionsWidget( parent );
}

QStringList QgsCustomProjectionOptionsFactory::path() const
{
return {QStringLiteral( "crs_and_transforms" ) };
}

@@ -1,5 +1,5 @@
/***************************************************************************
qgscustomprojectiondialog.h
qgscustomprojectionoptions.h
-------------------
begin : 2005
Expand All @@ -15,42 +15,45 @@
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSCUSTOMCRSDIALOG_H
#define QGSCUSTOMCRSDIALOG_H
#ifndef QGSCUSTOMPROJECTIONOPTIONS_H
#define QGSCUSTOMPROJECTIONOPTIONS_H

#include "ui_qgscustomprojectiondialogbase.h"
#include "qgsoptionswidgetfactory.h"
#include "qgshelp.h"
#include "qgscoordinatereferencesystem.h"
#include "qgis_app.h"

class QDir;

/**
* The custom projection widget is used to define the projection family, ellipsoid and parameters needed by proj4 to assemble a customized projection definition.
* \ingroup app
* \class QgsCustomProjectionOptionsWidget
* \brief The custom projection widget is used to define the projection family, ellipsoid and parameters needed by proj to assemble a customized projection definition.
*
* The resulting projection will be stored in an sqlite backend.
*/
class APP_EXPORT QgsCustomProjectionDialog : public QDialog, private Ui::QgsCustomProjectionDialogBase
*/
class QgsCustomProjectionOptionsWidget: public QgsOptionsPageWidget, private Ui::QgsCustomProjectionWidgetBase
{
Q_OBJECT
public:
QgsCustomProjectionDialog( QWidget *parent = nullptr, Qt::WindowFlags fl = Qt::WindowFlags() );
QgsCustomProjectionOptionsWidget( QWidget *parent = nullptr );

public slots:
QString helpKey() const override;
bool isValid() override;
void apply() override;

private slots:
void pbnAdd_clicked();
void pbnRemove_clicked();
void leNameList_currentItemChanged( QTreeWidgetItem *current, QTreeWidgetItem *prev );
void buttonBox_accepted();

private slots:

void updateListFromCurrentItem();

private:

//helper functions
void populateList();
bool saveCrs( QgsCoordinateReferenceSystem crs, const QString &name, const QString &id, bool newEntry, Qgis::CrsDefinitionFormat format );
void showHelp();
bool saveCrs( const QgsCoordinateReferenceSystem &crs, const QString &name, const QString &id, bool newEntry, Qgis::CrsDefinitionFormat format );
QString multiLineWktToSingleLine( const QString &wkt );

//These two QMap store the values as they are on the database when loading
Expand Down Expand Up @@ -81,8 +84,22 @@ class APP_EXPORT QgsCustomProjectionDialog : public QDialog, private Ui::QgsCust

int mBlockUpdates = 0;

};


class QgsCustomProjectionOptionsFactory : public QgsOptionsWidgetFactory
{
Q_OBJECT

public:

QgsCustomProjectionOptionsFactory();

QIcon icon() const override;
QgsOptionsPageWidget *createWidget( QWidget *parent = nullptr ) const override;
QStringList path() const override;

};


#endif
#endif // QGSCUSTOMPROJECTIONOPTIONS_H
1 change: 1 addition & 0 deletions src/app/options/qgsoptions.cpp
Expand Up @@ -110,6 +110,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
mTreeModel->appendRow( createItem( QCoreApplication::translate( "QgsOptionsBase", "System" ), QCoreApplication::translate( "QgsOptionsBase", "System" ), QStringLiteral( "propertyicons/system.svg" ) ) );

QStandardItem *crsGroup = new QStandardItem( QCoreApplication::translate( "QgsOptionsBase", "CRS and Transforms" ) );
crsGroup->setData( QStringLiteral( "crs_and_transforms" ) );
crsGroup->setToolTip( tr( "CRS and Transforms" ) );
crsGroup->setSelectable( false );
crsGroup->appendRow( createItem( QCoreApplication::translate( "QgsOptionsBase", "CRS" ), QCoreApplication::translate( "QgsOptionsBase", "CRS" ), QStringLiteral( "propertyicons/CRS.svg" ) ) );
Expand Down
9 changes: 3 additions & 6 deletions src/app/qgisapp.cpp
Expand Up @@ -114,6 +114,7 @@

#include "options/qgscodeeditoroptions.h"
#include "options/qgsgpsdeviceoptions.h"
#include "options/qgscustomprojectionoptions.h"

#ifdef HAVE_3D
#include "qgs3d.h"
Expand Down Expand Up @@ -215,7 +216,6 @@ Q_GUI_EXPORT extern int qt_defaultDpiX();
#include "qgscustomprojectopenhandler.h"
#include "qgscustomization.h"
#include "qgscustomlayerorderwidget.h"
#include "qgscustomprojectiondialog.h"
#include "qgsdataitemproviderregistry.h"
#include "qgsdataitemguiproviderregistry.h"
#include "qgsdatasourceuri.h"
Expand Down Expand Up @@ -1817,6 +1817,7 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipBadLayers

mCodeEditorWidgetFactory.reset( std::make_unique< QgsCodeEditorOptionsFactory >() );
mBabelGpsDevicesWidgetFactory.reset( std::make_unique< QgsGpsDeviceOptionsFactory >() );
mCustomProjectionsWidgetFactory.reset( std::make_unique< QgsCustomProjectionOptionsFactory >() );

#ifdef HAVE_3D
m3DOptionsWidgetFactory.reset( std::make_unique< Qgs3DOptionsFactory >() );
Expand Down Expand Up @@ -16584,11 +16585,7 @@ void QgisApp::mapCanvas_keyPressed( QKeyEvent *e )

void QgisApp::customProjection()
{
// Create an instance of the Custom Projection Designer modeless dialog.
// Autodelete the dialog when closing since a pointer is not retained.
QgsCustomProjectionDialog *myDialog = new QgsCustomProjectionDialog( this );
myDialog->setAttribute( Qt::WA_DeleteOnClose );
myDialog->show();
showOptionsDialog( this, QStringLiteral( "QgsCustomProjectionOptionsWidget" ) );
}

void QgisApp::newBookmark( bool inProject )
Expand Down

0 comments on commit e8f427a

Please sign in to comment.