Skip to content

Commit 3c7c65e

Browse files
committed
Allow a "no projection" option in projection selection widget/dialog
This option allows users to select "no projection", when there's no suitable projection to select...
1 parent 9dd71b8 commit 3c7c65e

8 files changed

+149
-6
lines changed

python/gui/qgsprojectionselectiondialog.sip

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ class QgsProjectionSelectionDialog : QDialog //, private Ui::QgsGenericProjectio
1818

1919
void setMessage( const QString& message );
2020

21+
void setShowNoProjection( bool show );
22+
23+
bool showNoProjection() const;
24+
2125
public slots:
2226

2327

python/gui/qgsprojectionselectiontreewidget.sip

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@ class QgsProjectionSelectionTreeWidget : QWidget
55
%End
66

77
public:
8-
QgsProjectionSelectionTreeWidget( QWidget* parent /TransferThis/ );
8+
QgsProjectionSelectionTreeWidget( QWidget* parent /TransferThis/ = 0 );
99

1010
~QgsProjectionSelectionTreeWidget();
1111

1212
QgsCoordinateReferenceSystem crs() const;
1313

14+
void setShowNoProjection( bool show );
15+
16+
bool showNoProjection() const;
17+
18+
bool hasValidSelection() const;
19+
1420
public slots:
1521

1622
void setCrs( const QgsCoordinateReferenceSystem& crs );

src/gui/qgsprojectionselectiondialog.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,16 @@ void QgsProjectionSelectionDialog::setMessage( const QString& message )
5959
textEdit->show();
6060
}
6161

62+
void QgsProjectionSelectionDialog::setShowNoProjection( bool show )
63+
{
64+
projectionSelector->setShowNoProjection( show );
65+
}
66+
67+
bool QgsProjectionSelectionDialog::showNoProjection() const
68+
{
69+
return projectionSelector->showNoProjection();
70+
}
71+
6272
QgsProjectionSelectionDialog::~QgsProjectionSelectionDialog()
6373
{
6474
QSettings settings;

src/gui/qgsprojectionselectiondialog.h

+16
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,22 @@ class GUI_EXPORT QgsProjectionSelectionDialog : public QDialog, private Ui::QgsG
7676
*/
7777
void setMessage( const QString& message );
7878

79+
/**
80+
* Sets whether a "no/invalid" projection option should be shown. If this
81+
* option is selected, calling crs() will return an invalid QgsCoordinateReferenceSystem.
82+
* @see showNoProjection()
83+
* @note added in QGIS 3.0
84+
*/
85+
void setShowNoProjection( bool show );
86+
87+
/**
88+
* Returns whether the "no/invalid" projection option is shown. If this
89+
* option is selected, calling crs() will return an invalid QgsCoordinateReferenceSystem.
90+
* @note added in QGIS 3.0
91+
* @see setShowNoProjection()
92+
*/
93+
bool showNoProjection() const;
94+
7995
public slots:
8096

8197
/**

src/gui/qgsprojectionselectiontreewidget.cpp

+33-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ QgsProjectionSelectionTreeWidget::QgsProjectionSelectionTreeWidget( QWidget* par
6464
lstRecent->setColumnHidden( QgisCrsIdColumn, true );
6565

6666
mRecentProjections = QgsCoordinateReferenceSystem::recentProjections();
67+
68+
mNoProjItem = new QTreeWidgetItem( lstCoordinateSystems, QStringList( tr( "No projection" ) ) );
69+
mNoProjItem->setHidden( true );
6770
}
6871

6972
QgsProjectionSelectionTreeWidget::~QgsProjectionSelectionTreeWidget()
@@ -268,7 +271,14 @@ QString QgsProjectionSelectionTreeWidget::selectedName()
268271

269272
void QgsProjectionSelectionTreeWidget::setCrs( const QgsCoordinateReferenceSystem& crs )
270273
{
271-
applySelection( AuthidColumn, crs.authid() );
274+
if ( !crs.isValid() )
275+
{
276+
lstCoordinateSystems->setCurrentItem( mNoProjItem );
277+
}
278+
else
279+
{
280+
applySelection( AuthidColumn, crs.authid() );
281+
}
272282
}
273283

274284
// Returns the whole proj4 string for the selected projection node
@@ -414,13 +424,35 @@ QString QgsProjectionSelectionTreeWidget::getSelectedExpression( const QString&
414424

415425
QgsCoordinateReferenceSystem QgsProjectionSelectionTreeWidget::crs() const
416426
{
427+
if ( lstCoordinateSystems->currentItem() == mNoProjItem )
428+
return QgsCoordinateReferenceSystem();
429+
417430
int srid = getSelectedExpression( QStringLiteral( "srs_id" ) ).toLong();
418431
if ( srid >= USER_CRS_START_ID )
419432
return QgsCoordinateReferenceSystem::fromOgcWmsCrs( QString( "USER:%1" ).arg( srid ) );
420433
else
421434
return QgsCoordinateReferenceSystem::fromOgcWmsCrs( getSelectedExpression( QStringLiteral( "upper(auth_name||':'||auth_id)" ) ) );
422435
}
423436

437+
void QgsProjectionSelectionTreeWidget::setShowNoProjection( bool show )
438+
{
439+
mNoProjItem->setHidden( !show );
440+
}
441+
442+
bool QgsProjectionSelectionTreeWidget::showNoProjection() const
443+
{
444+
return !mNoProjItem->isHidden();
445+
}
446+
447+
bool QgsProjectionSelectionTreeWidget::hasValidSelection() const
448+
{
449+
QTreeWidgetItem* item = lstCoordinateSystems->currentItem();
450+
if ( item == mNoProjItem )
451+
return true;
452+
else
453+
return item && !item->text( QgisCrsIdColumn ).isEmpty();
454+
}
455+
424456
long QgsProjectionSelectionTreeWidget::selectedCrsId()
425457
{
426458
QTreeWidgetItem* item = lstCoordinateSystems->currentItem();

src/gui/qgsprojectionselectiontreewidget.h

+26
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,30 @@ class GUI_EXPORT QgsProjectionSelectionTreeWidget : public QWidget, private Ui::
5656
*/
5757
QgsCoordinateReferenceSystem crs() const;
5858

59+
/**
60+
* Sets whether a "no/invalid" projection option should be shown. If this
61+
* option is selected, calling crs() will return an invalid QgsCoordinateReferenceSystem.
62+
* @see showNoProjection()
63+
* @note added in QGIS 3.0
64+
*/
65+
void setShowNoProjection( bool show );
66+
67+
/**
68+
* Returns whether the "no/invalid" projection option is shown. If this
69+
* option is selected, calling crs() will return an invalid QgsCoordinateReferenceSystem.
70+
* @note added in QGIS 3.0
71+
* @see setShowNoProjection()
72+
*/
73+
bool showNoProjection() const;
74+
75+
/**
76+
* Returns true if the current selection in the widget is a valid choice. Valid
77+
* selections include any projection and also the "no/invalid projection" option
78+
* (if setShowNoProjection() was called). Invalid selections are the group
79+
* headers (such as "Geographic Coordinate Systems"
80+
*/
81+
bool hasValidSelection() const;
82+
5983
public slots:
6084

6185
/**
@@ -189,6 +213,8 @@ class GUI_EXPORT QgsProjectionSelectionTreeWidget : public QWidget, private Ui::
189213
QTreeWidgetItem *mGeoList = nullptr;
190214
//! PROJCS node
191215
QTreeWidgetItem *mProjList = nullptr;
216+
//! "No projection" item
217+
QTreeWidgetItem* mNoProjItem = nullptr;
192218

193219
//! Users custom coordinate system file
194220
QString mCustomCsFile;

tests/src/python/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ ADD_PYTHON_TEST(PyQgsPanelWidgetStack test_qgspanelwidgetstack.py)
9090
ADD_PYTHON_TEST(PyQgsPoint test_qgspoint.py)
9191
ADD_PYTHON_TEST(PyQgsPointClusterRenderer test_qgspointclusterrenderer.py)
9292
ADD_PYTHON_TEST(PyQgsPointDisplacementRenderer test_qgspointdisplacementrenderer.py)
93-
ADD_PYTHON_TEST(PyQgsProjectionSelectionWidget test_qgsprojectionselectionwidget.py)
93+
ADD_PYTHON_TEST(PyQgsProjectionSelectionWidgets test_qgsprojectionselectionwidgets.py)
9494
ADD_PYTHON_TEST(PyQgsRangeWidgets test_qgsrangewidgets.py)
9595
ADD_PYTHON_TEST(PyQgsRasterFileWriter test_qgsrasterfilewriter.py)
9696
ADD_PYTHON_TEST(PyQgsRasterLayer test_qgsrasterlayer.py)

tests/src/python/test_qgsprojectionselectionwidget.py renamed to tests/src/python/test_qgsprojectionselectionwidgets.py

+52-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# -*- coding: utf-8 -*-
2-
"""QGIS Unit tests for QgsProjectionSelectionWidget.
2+
"""QGIS Unit tests for various projection selection widgets.
33
44
.. note:: This program is free software; you can redistribute it and/or modify
55
it under the terms of the GNU General Public License as published by
@@ -14,14 +14,16 @@
1414

1515
import qgis # NOQA
1616

17-
from qgis.gui import QgsProjectionSelectionWidget
17+
from qgis.gui import (QgsProjectionSelectionWidget,
18+
QgsProjectionSelectionTreeWidget,
19+
QgsProjectionSelectionDialog)
1820
from qgis.core import QgsCoordinateReferenceSystem, QgsProject
1921
from qgis.testing import start_app, unittest
2022
from qgis.PyQt.QtGui import QColor
2123
start_app()
2224

2325

24-
class TestQgsProjectionSelectionWidget(unittest.TestCase):
26+
class TestQgsProjectionSelectionWidgets(unittest.TestCase):
2527

2628
def testShowingHiding(self):
2729
""" test showing and hiding options """
@@ -112,6 +114,53 @@ def testShowingNotSetOption(self):
112114
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.CurrentCrs))
113115
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.CrsNotSet))
114116

117+
def testTreeWidgetGettersSetters(self):
118+
""" basic tests for QgsProjectionSelectionTreeWidget """
119+
w = QgsProjectionSelectionTreeWidget()
120+
w.show()
121+
self.assertFalse(w.hasValidSelection())
122+
w.setCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
123+
self.assertEqual(w.crs().authid(),'EPSG:3111')
124+
self.assertTrue(w.hasValidSelection())
125+
126+
127+
def testTreeWidgetNotSetOption(self):
128+
""" test allowing no projection option for QgsProjectionSelectionTreeWidget """
129+
w = QgsProjectionSelectionTreeWidget()
130+
w.show()
131+
w.setShowNoProjection(True)
132+
self.assertTrue(w.showNoProjection())
133+
w.setShowNoProjection(False)
134+
self.assertFalse(w.showNoProjection())
135+
136+
w.setShowNoProjection(True)
137+
# no projection should be a valid selection
138+
w.setCrs(QgsCoordinateReferenceSystem())
139+
self.assertTrue(w.hasValidSelection())
140+
self.assertFalse(w.crs().isValid())
141+
142+
def testDialogGettersSetters(self):
143+
""" basic tests for QgsProjectionSelectionTreeWidget """
144+
w = QgsProjectionSelectionDialog()
145+
w.show()
146+
w.setCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
147+
self.assertEqual(w.crs().authid(),'EPSG:3111')
148+
149+
def testDialogNotSetOption(self):
150+
""" test allowing no projection option for QgsProjectionSelectionTreeWidget """
151+
w = QgsProjectionSelectionDialog()
152+
w.show()
153+
w.setShowNoProjection(True)
154+
self.assertTrue(w.showNoProjection())
155+
w.setShowNoProjection(False)
156+
self.assertFalse(w.showNoProjection())
157+
158+
w.setShowNoProjection(True)
159+
w.setCrs(QgsCoordinateReferenceSystem())
160+
self.assertFalse(w.crs().isValid())
161+
162+
163+
115164

116165
if __name__ == '__main__':
117166
unittest.main()

0 commit comments

Comments
 (0)