Skip to content

Commit

Permalink
Allow showing 'not set' in QgsProjectionSelectionWidget
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Nov 13, 2016
1 parent 08231b8 commit fbc12a8
Show file tree
Hide file tree
Showing 5 changed files with 254 additions and 6 deletions.
25 changes: 24 additions & 1 deletion python/gui/qgsprojectionselectionwidget.sip
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ class QgsProjectionSelectionWidget : QWidget
ProjectCrs, /*!< current project CRS (if OTF reprojection enabled) */
CurrentCrs, /*!< current user selected CRS */
DefaultCrs, /*!< global default QGIS CRS */
RecentCrs /*!< recently used CRS */
RecentCrs, //!< Recently used CRS
CrsNotSet, //!< Not set (hidden by default)
};

explicit QgsProjectionSelectionWidget( QWidget *parent /TransferThis/ = 0 );
Expand All @@ -39,15 +40,37 @@ class QgsProjectionSelectionWidget : QWidget
/** Sets whether a predefined CRS option should be shown in the widget.
* @param option CRS option to show/hide
* @param visible whether the option should be shown
* @see optionVisible()
*/
void setOptionVisible( const CrsOption option, const bool visible );


/**
* Returns whether the specified CRS option is visible in the widget.
* @note added in QGIS 3.0
* @see setOptionVisible()
*/
bool optionVisible( CrsOption option ) const;

/**
* Sets the text to show for the not set option. Note that this option is not shown
* by default and must be set visible by calling setOptionVisible().
* @note added in QGIS 3.0
*/
void setNotSetText( const QString& text );

signals:

/** Emitted when the selected CRS is changed
*/
void crsChanged( const QgsCoordinateReferenceSystem& );

/**
* Emitted when the not set option is selected.
* @note added in QGIS 3.0
*/
void cleared();

public slots:

/** Sets the current CRS for the widget
Expand Down
84 changes: 80 additions & 4 deletions src/gui/qgsprojectionselectionwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ QgsCoordinateReferenceSystem QgsProjectionSelectionWidget::crs() const
QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromSrsId( srsid );
return crs;
}
case QgsProjectionSelectionWidget::CrsNotSet:
return QgsCoordinateReferenceSystem();
}
return mCrs;
}
Expand Down Expand Up @@ -117,18 +119,55 @@ void QgsProjectionSelectionWidget::setOptionVisible( const QgsProjectionSelectio
return;
}
case QgsProjectionSelectionWidget::CurrentCrs:
{
addCurrentCrsOption();
return;
}
case QgsProjectionSelectionWidget::RecentCrs:
//current/recently used CRS option cannot be readded
//recently used CRS option cannot be readded
return;
case QgsProjectionSelectionWidget::CrsNotSet:
{
addNotSetOption();

if ( optionVisible( CurrentCrs ) && !mCrs.isValid() )
{
// hide invalid option if not set option is shown
setOptionVisible( CurrentCrs, false );
}

return;
}
}
}
else if ( !visible && optionIndex >= 0 )
{
//remove CRS option
mCrsComboBox->removeItem( optionIndex );

if ( option == CrsNotSet )
{
setOptionVisible( CurrentCrs, true );
}
}
}

void QgsProjectionSelectionWidget::setNotSetText( const QString& text )
{
mNotSetText = text;
int optionIndex = mCrsComboBox->findData( CrsNotSet );
if ( optionIndex >= 0 )
{
mCrsComboBox->setItemText( optionIndex, mNotSetText );
}
}

bool QgsProjectionSelectionWidget::optionVisible( QgsProjectionSelectionWidget::CrsOption option ) const
{
int optionIndex = mCrsComboBox->findData( option );
return optionIndex >= 0;
}

void QgsProjectionSelectionWidget::selectCrs()
{
//find out crs id of current proj4 string
Expand All @@ -152,6 +191,13 @@ void QgsProjectionSelectionWidget::selectCrs()
}
}

void QgsProjectionSelectionWidget::addNotSetOption()
{
mCrsComboBox->insertItem( 0, mNotSetText, QgsProjectionSelectionWidget::CrsNotSet );
if ( !mCrs.isValid() )
whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
}

void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
{
switch (( CrsOption )mCrsComboBox->itemData( idx ).toInt() )
Expand All @@ -175,23 +221,38 @@ void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
emit crsChanged( crs );
return;
}
case QgsProjectionSelectionWidget::CrsNotSet:
emit cleared();
return;
}
}

void QgsProjectionSelectionWidget::setCrs( const QgsCoordinateReferenceSystem& crs )
{
if ( crs.isValid() )
{
if ( !optionVisible( QgsProjectionSelectionWidget::CurrentCrs ) )
setOptionVisible( QgsProjectionSelectionWidget::CurrentCrs, true );
mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
tr( "Selected CRS (%1, %2)" ).arg( crs.authid(), crs.description() ) );
currentCrsOptionText( crs ) );
mCrsComboBox->blockSignals( true );
mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ) );
mCrsComboBox->blockSignals( false );
}
else
{
mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
tr( "invalid projection" ) );
int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet );
if ( crsNotSetIndex >= 0 )
{
mCrsComboBox->blockSignals( true );
mCrsComboBox->setCurrentIndex( crsNotSetIndex );
mCrsComboBox->blockSignals( false );
}
else
{
mCrsComboBox->setItemText( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs ),
currentCrsOptionText( crs ) );
}
}
mCrs = crs;
}
Expand Down Expand Up @@ -233,6 +294,21 @@ void QgsProjectionSelectionWidget::addDefaultCrsOption()
mCrsComboBox->addItem( tr( "Default CRS (%1 - %2)" ).arg( mDefaultCrs.authid(), mDefaultCrs.description() ), QgsProjectionSelectionWidget::DefaultCrs );
}

void QgsProjectionSelectionWidget::addCurrentCrsOption()
{
int index = optionVisible( CrsNotSet ) ? 1 : 0;
mCrsComboBox->insertItem( index, currentCrsOptionText( mCrs ), QgsProjectionSelectionWidget::CurrentCrs );

}

QString QgsProjectionSelectionWidget::currentCrsOptionText( const QgsCoordinateReferenceSystem& crs ) const
{
if ( crs.isValid() )
return tr( "Selected CRS (%1, %2)" ).arg( crs.authid(), crs.description() );
else
return tr( "invalid projection" );
}

void QgsProjectionSelectionWidget::addRecentCrs()
{
QStringList recentProjections = QgsCoordinateReferenceSystem::recentProjections();
Expand Down
28 changes: 27 additions & 1 deletion src/gui/qgsprojectionselectionwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ class GUI_EXPORT QgsProjectionSelectionWidget : public QWidget
ProjectCrs, //!< Current project CRS (if OTF reprojection enabled)
CurrentCrs, //!< Current user selected CRS
DefaultCrs, //!< Global default QGIS CRS
RecentCrs //!< Recently used CRS
RecentCrs, //!< Recently used CRS
CrsNotSet, //!< Not set (hidden by default)
};

explicit QgsProjectionSelectionWidget( QWidget *parent = nullptr );
Expand All @@ -64,15 +65,36 @@ class GUI_EXPORT QgsProjectionSelectionWidget : public QWidget
/** Sets whether a predefined CRS option should be shown in the widget.
* @param option CRS option to show/hide
* @param visible whether the option should be shown
* @see optionVisible()
*/
void setOptionVisible( const CrsOption option, const bool visible );

/**
* Returns whether the specified CRS option is visible in the widget.
* @note added in QGIS 3.0
* @see setOptionVisible()
*/
bool optionVisible( CrsOption option ) const;

/**
* Sets the text to show for the not set option. Note that this option is not shown
* by default and must be set visible by calling setOptionVisible().
* @note added in QGIS 3.0
*/
void setNotSetText( const QString& text );

signals:

/** Emitted when the selected CRS is changed
*/
void crsChanged( const QgsCoordinateReferenceSystem& );

/**
* Emitted when the not set option is selected.
* @note added in QGIS 3.0
*/
void cleared();

public slots:

/** Sets the current CRS for the widget
Expand All @@ -99,9 +121,13 @@ class GUI_EXPORT QgsProjectionSelectionWidget : public QWidget
QComboBox* mCrsComboBox;
QToolButton* mButton;
QgsGenericProjectionSelector* mDialog;
QString mNotSetText;

void addNotSetOption();
void addProjectCrsOption();
void addDefaultCrsOption();
void addCurrentCrsOption();
QString currentCrsOptionText( const QgsCoordinateReferenceSystem& crs ) const;
void addRecentCrs();
bool crsIsShown( const long srsid ) const;

Expand Down
1 change: 1 addition & 0 deletions tests/src/python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ ADD_PYTHON_TEST(PyQgsPanelWidgetStack test_qgspanelwidgetstack.py)
ADD_PYTHON_TEST(PyQgsPoint test_qgspoint.py)
ADD_PYTHON_TEST(PyQgsPointClusterRenderer test_qgspointclusterrenderer.py)
ADD_PYTHON_TEST(PyQgsPointDisplacementRenderer test_qgspointdisplacementrenderer.py)
ADD_PYTHON_TEST(PyQgsProjectionSelectionWidget test_qgsprojectionselectionwidget.py)
ADD_PYTHON_TEST(PyQgsRangeWidgets test_qgsrangewidgets.py)
ADD_PYTHON_TEST(PyQgsRasterFileWriter test_qgsrasterfilewriter.py)
ADD_PYTHON_TEST(PyQgsRasterLayer test_qgsrasterlayer.py)
Expand Down
122 changes: 122 additions & 0 deletions tests/src/python/test_qgsprojectionselectionwidget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# -*- coding: utf-8 -*-
"""QGIS Unit tests for QgsProjectionSelectionWidget.
.. note:: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
"""
__author__ = 'Nyall Dawson'
__date__ = '12/11/2016'
__copyright__ = 'Copyright 2016, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'

import qgis # NOQA

from qgis.gui import QgsProjectionSelectionWidget
from qgis.core import QgsCoordinateReferenceSystem, QgsProject
from qgis.testing import start_app, unittest
from qgis.PyQt.QtGui import QColor
start_app()


class TestQgsProjectionSelectionWidget(unittest.TestCase):

def testShowingHiding(self):
""" test showing and hiding options """
w = QgsProjectionSelectionWidget()

# layer crs
w.setOptionVisible(QgsProjectionSelectionWidget.LayerCrs, False)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.LayerCrs))
w.setOptionVisible(QgsProjectionSelectionWidget.LayerCrs, True)
# should still be hidden, because layer crs not set
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.LayerCrs))
w.setLayerCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.LayerCrs))
w.setOptionVisible(QgsProjectionSelectionWidget.LayerCrs, False)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.LayerCrs))

# project crs
w.setOptionVisible(QgsProjectionSelectionWidget.ProjectCrs, False)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.ProjectCrs))
w.setOptionVisible(QgsProjectionSelectionWidget.ProjectCrs, True)
# should still be hidden, because project crs was not set
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.ProjectCrs))
QgsProject.instance().setCrs(QgsCoordinateReferenceSystem('EPSG:3113'))
w = QgsProjectionSelectionWidget()
w.setOptionVisible(QgsProjectionSelectionWidget.ProjectCrs, True)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.ProjectCrs))
# should still be hidden, because otf reprojection not active
QgsProject.instance().writeEntry("SpatialRefSys", "/ProjectionsEnabled", 1)
w = QgsProjectionSelectionWidget()
w.setOptionVisible(QgsProjectionSelectionWidget.ProjectCrs, True)
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.ProjectCrs))
w.setOptionVisible(QgsProjectionSelectionWidget.ProjectCrs, False)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.ProjectCrs))

# default crs
w.setOptionVisible(QgsProjectionSelectionWidget.DefaultCrs, False)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.DefaultCrs))
w.setOptionVisible(QgsProjectionSelectionWidget.DefaultCrs, True)
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.DefaultCrs))

# current crs
w = QgsProjectionSelectionWidget()
w.setOptionVisible(QgsProjectionSelectionWidget.CurrentCrs, False)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.CurrentCrs))
w.setOptionVisible(QgsProjectionSelectionWidget.CurrentCrs, True)
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.CurrentCrs))

w = QgsProjectionSelectionWidget()
w.setCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
w.setOptionVisible(QgsProjectionSelectionWidget.CurrentCrs, False)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.CurrentCrs))
w.setOptionVisible(QgsProjectionSelectionWidget.CurrentCrs, True)
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.CurrentCrs))

# not set
w = QgsProjectionSelectionWidget()
w.setOptionVisible(QgsProjectionSelectionWidget.CrsNotSet, False)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.CrsNotSet))
w.setOptionVisible(QgsProjectionSelectionWidget.CrsNotSet, True)
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.CrsNotSet))
w.setOptionVisible(QgsProjectionSelectionWidget.CrsNotSet, False)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.CrsNotSet))

def testShowingNotSetOption(self):
""" test showing the not set option """

w = QgsProjectionSelectionWidget()
# start with an invalid CRS
w.setCrs(QgsCoordinateReferenceSystem())
# add the not-set option
w.setOptionVisible(QgsProjectionSelectionWidget.CrsNotSet, True)
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.CrsNotSet))
# current crs (which would show "invalid") should be hidden
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.CurrentCrs))
# hide not-set option
w.setOptionVisible(QgsProjectionSelectionWidget.CrsNotSet, False)
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.CrsNotSet))
# and now current crs option ('invalid') should be reshown
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.CurrentCrs))

# repeat with a slightly different workflow
w = QgsProjectionSelectionWidget()
# start with an invalid CRS
w.setCrs(QgsCoordinateReferenceSystem())
# add the not-set option
w.setOptionVisible(QgsProjectionSelectionWidget.CrsNotSet, True)
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.CrsNotSet))
# current crs (which would show "invalid") should be hidden
self.assertFalse(w.optionVisible(QgsProjectionSelectionWidget.CurrentCrs))
# now set a current crs
w.setCrs(QgsCoordinateReferenceSystem('EPSG:3111'))
# both current and not set options should be shown
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.CurrentCrs))
self.assertTrue(w.optionVisible(QgsProjectionSelectionWidget.CrsNotSet))


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

0 comments on commit fbc12a8

Please sign in to comment.