Add proxy model for recent crs model

This commit is contained in:
Nyall Dawson 2024-01-16 15:24:31 +10:00
parent d2c380572f
commit e53e078bca
6 changed files with 357 additions and 1 deletions

View File

@ -7,3 +7,9 @@ QgsRecentCoordinateReferenceSystemsModel.RoleType = QgsRecentCoordinateReference
QgsRecentCoordinateReferenceSystemsModel.RoleGroupId = QgsRecentCoordinateReferenceSystemsModel.Roles.RoleGroupId
QgsRecentCoordinateReferenceSystemsModel.RoleWkt = QgsRecentCoordinateReferenceSystemsModel.Roles.RoleWkt
QgsRecentCoordinateReferenceSystemsModel.RoleProj = QgsRecentCoordinateReferenceSystemsModel.Roles.RoleProj
QgsRecentCoordinateReferenceSystemsProxyModel.FilterHorizontal = QgsRecentCoordinateReferenceSystemsProxyModel.Filter.FilterHorizontal
QgsRecentCoordinateReferenceSystemsProxyModel.FilterVertical = QgsRecentCoordinateReferenceSystemsProxyModel.Filter.FilterVertical
QgsRecentCoordinateReferenceSystemsProxyModel.FilterCompound = QgsRecentCoordinateReferenceSystemsProxyModel.Filter.FilterCompound
QgsRecentCoordinateReferenceSystemsProxyModel.Filters = lambda flags=0: QgsRecentCoordinateReferenceSystemsProxyModel.Filter(flags)
QgsRecentCoordinateReferenceSystemsProxyModel.Filters.baseClass = QgsRecentCoordinateReferenceSystemsProxyModel
Filters = QgsRecentCoordinateReferenceSystemsProxyModel # dirty hack since SIP seems to introduce the flags in module

View File

@ -63,6 +63,69 @@ Returns an invalid CRS if the index is not valid.
};
class QgsRecentCoordinateReferenceSystemsProxyModel: QSortFilterProxyModel
{
%Docstring(signature="appended")
A sort/filter proxy model for recent coordinate reference systems.
.. versionadded:: 3.36
%End
%TypeHeaderCode
#include "qgsrecentcoordinatereferencesystemsmodel.h"
%End
public:
enum Filter
{
FilterHorizontal,
FilterVertical,
FilterCompound,
};
typedef QFlags<QgsRecentCoordinateReferenceSystemsProxyModel::Filter> Filters;
explicit QgsRecentCoordinateReferenceSystemsProxyModel( QObject *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsRecentCoordinateReferenceSystemsProxyModel, with the given ``parent`` object.
%End
QgsRecentCoordinateReferenceSystemsModel *recentCoordinateReferenceSystemsModel();
%Docstring
Returns the underlying source model.
%End
void setFilters( QgsRecentCoordinateReferenceSystemsProxyModel::Filters filters );
%Docstring
Set ``filters`` that affect how CRS are filtered.
.. seealso:: :py:func:`filters`
%End
Filters filters() const;
%Docstring
Returns any filters that affect how CRS are filtered.
.. seealso:: :py:func:`setFilters`
%End
virtual bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const;
QgsCoordinateReferenceSystem crs( const QModelIndex &index ) const;
%Docstring
Returns the CRS for the corresponding ``index``.
Returns an invalid CRS if the index is not valid.
%End
};
QFlags<QgsRecentCoordinateReferenceSystemsProxyModel::Filter> operator|(QgsRecentCoordinateReferenceSystemsProxyModel::Filter f1, QFlags<QgsRecentCoordinateReferenceSystemsProxyModel::Filter> f2);
/************************************************************************
* This file has been generated automatically from *
* *

View File

@ -63,6 +63,69 @@ Returns an invalid CRS if the index is not valid.
};
class QgsRecentCoordinateReferenceSystemsProxyModel: QSortFilterProxyModel
{
%Docstring(signature="appended")
A sort/filter proxy model for recent coordinate reference systems.
.. versionadded:: 3.36
%End
%TypeHeaderCode
#include "qgsrecentcoordinatereferencesystemsmodel.h"
%End
public:
enum Filter
{
FilterHorizontal,
FilterVertical,
FilterCompound,
};
typedef QFlags<QgsRecentCoordinateReferenceSystemsProxyModel::Filter> Filters;
explicit QgsRecentCoordinateReferenceSystemsProxyModel( QObject *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsRecentCoordinateReferenceSystemsProxyModel, with the given ``parent`` object.
%End
QgsRecentCoordinateReferenceSystemsModel *recentCoordinateReferenceSystemsModel();
%Docstring
Returns the underlying source model.
%End
void setFilters( QgsRecentCoordinateReferenceSystemsProxyModel::Filters filters );
%Docstring
Set ``filters`` that affect how CRS are filtered.
.. seealso:: :py:func:`filters`
%End
Filters filters() const;
%Docstring
Returns any filters that affect how CRS are filtered.
.. seealso:: :py:func:`setFilters`
%End
virtual bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const;
QgsCoordinateReferenceSystem crs( const QModelIndex &index ) const;
%Docstring
Returns the CRS for the corresponding ``index``.
Returns an invalid CRS if the index is not valid.
%End
};
QFlags<QgsRecentCoordinateReferenceSystemsProxyModel::Filter> operator|(QgsRecentCoordinateReferenceSystemsProxyModel::Filter f1, QFlags<QgsRecentCoordinateReferenceSystemsProxyModel::Filter> f2);
/************************************************************************
* This file has been generated automatically from *
* *

View File

@ -129,3 +129,83 @@ void QgsRecentCoordinateReferenceSystemsModel::recentCrsCleared()
mCrs.clear();
endResetModel();
}
//
// QgsRecentCoordinateReferenceSystemsProxyModel
//
QgsRecentCoordinateReferenceSystemsProxyModel::QgsRecentCoordinateReferenceSystemsProxyModel( QObject *parent )
: QSortFilterProxyModel( parent )
, mModel( new QgsRecentCoordinateReferenceSystemsModel( this ) )
{
setSourceModel( mModel );
setDynamicSortFilter( true );
}
QgsRecentCoordinateReferenceSystemsModel *QgsRecentCoordinateReferenceSystemsProxyModel::recentCoordinateReferenceSystemsModel()
{
return mModel;
}
const QgsRecentCoordinateReferenceSystemsModel *QgsRecentCoordinateReferenceSystemsProxyModel::recentCoordinateReferenceSystemsModel() const
{
return mModel;
}
void QgsRecentCoordinateReferenceSystemsProxyModel::setFilters( QgsRecentCoordinateReferenceSystemsProxyModel::Filters filters )
{
if ( mFilters == filters )
return;
mFilters = filters;
invalidateFilter();
}
bool QgsRecentCoordinateReferenceSystemsProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
{
if ( !mFilters )
return true;
const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
const Qgis::CrsType type = mModel->crs( sourceIndex ).type();
switch ( type )
{
case Qgis::CrsType::Unknown:
case Qgis::CrsType::Other:
break;
case Qgis::CrsType::Geodetic:
case Qgis::CrsType::Geocentric:
case Qgis::CrsType::Geographic2d:
case Qgis::CrsType::Geographic3d:
case Qgis::CrsType::Projected:
case Qgis::CrsType::Temporal:
case Qgis::CrsType::Engineering:
case Qgis::CrsType::Bound:
case Qgis::CrsType::DerivedProjected:
if ( !mFilters.testFlag( Filter::FilterHorizontal ) )
return false;
break;
case Qgis::CrsType::Vertical:
if ( !mFilters.testFlag( Filter::FilterVertical ) )
return false;
break;
case Qgis::CrsType::Compound:
if ( !mFilters.testFlag( Filter::FilterCompound ) )
return false;
break;
}
return true;
}
QgsCoordinateReferenceSystem QgsRecentCoordinateReferenceSystemsProxyModel::crs( const QModelIndex &index ) const
{
const QModelIndex sourceIndex = mapToSource( index );
return mModel->crs( sourceIndex );
}

View File

@ -84,4 +84,72 @@ class GUI_EXPORT QgsRecentCoordinateReferenceSystemsModel : public QAbstractItem
};
/**
* \brief A sort/filter proxy model for recent coordinate reference systems.
*
* \ingroup gui
* \since QGIS 3.36
*/
class GUI_EXPORT QgsRecentCoordinateReferenceSystemsProxyModel: public QSortFilterProxyModel
{
Q_OBJECT
public:
//! Available filter flags for filtering the model
enum Filter
{
FilterHorizontal = 1 << 1, //!< Include horizontal CRS (excludes compound CRS containing a horizontal component)
FilterVertical = 1 << 2, //!< Include vertical CRS (excludes compound CRS containing a vertical component)
FilterCompound = 1 << 3, //!< Include compound CRS
};
Q_DECLARE_FLAGS( Filters, Filter )
Q_FLAG( Filters )
/**
* Constructor for QgsRecentCoordinateReferenceSystemsProxyModel, with the given \a parent object.
*/
explicit QgsRecentCoordinateReferenceSystemsProxyModel( QObject *parent SIP_TRANSFERTHIS = nullptr );
/**
* Returns the underlying source model.
*/
QgsRecentCoordinateReferenceSystemsModel *recentCoordinateReferenceSystemsModel();
/**
* Returns the underlying source model.
* \note Not available in Python bindings
*/
const QgsRecentCoordinateReferenceSystemsModel *recentCoordinateReferenceSystemsModel() const SIP_SKIP;
/**
* Set \a filters that affect how CRS are filtered.
* \see filters()
*/
void setFilters( QgsRecentCoordinateReferenceSystemsProxyModel::Filters filters );
/**
* Returns any filters that affect how CRS are filtered.
* \see setFilters()
*/
Filters filters() const { return mFilters; }
bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const override;
/**
* Returns the CRS for the corresponding \a index.
*
* Returns an invalid CRS if the index is not valid.
*/
QgsCoordinateReferenceSystem crs( const QModelIndex &index ) const;
private:
QgsRecentCoordinateReferenceSystemsModel *mModel = nullptr;
Filters mFilters = Filters();
};
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsRecentCoordinateReferenceSystemsProxyModel::Filters )
#endif // QGSRECENTCOORDINATEREFERENCESYSTEMSMODEL_H

View File

@ -19,11 +19,11 @@ from qgis.core import (
Qgis,
QgsApplication,
QgsCoordinateReferenceSystem,
QgsCoordinateReferenceSystemUtils,
QgsSettings,
)
from qgis.gui import (
QgsRecentCoordinateReferenceSystemsModel,
QgsRecentCoordinateReferenceSystemsProxyModel
)
import unittest
@ -155,6 +155,82 @@ class TestQgsRecentCoordinateReferenceSystemsModel(QgisTestCase):
)
self.assertEqual(model.rowCount(), 46)
def test_proxy(self):
registry = QgsApplication.coordinateReferenceSystemRegistry()
registry.clearRecent()
model = QgsRecentCoordinateReferenceSystemsProxyModel()
# should initially be nothing in the model
self.assertEqual(model.rowCount(), 0)
self.assertFalse(model.index(-1, 0, QModelIndex()).isValid())
self.assertFalse(model.index(0, 0, QModelIndex()).isValid())
self.assertFalse(model.index(1, 0, QModelIndex()).isValid())
self.assertIsNone(
model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole))
self.assertFalse(model.crs(model.index(0, 0, QModelIndex())).isValid())
self.assertFalse(
model.crs(model.index(-1, 0, QModelIndex())).isValid())
self.assertFalse(model.crs(model.index(1, 0, QModelIndex())).isValid())
# push a crs
registry.pushRecent(QgsCoordinateReferenceSystem('EPSG:3111'))
self.assertEqual(model.rowCount(), 1)
self.assertTrue(model.index(0, 0, QModelIndex()).isValid())
self.assertFalse(model.index(1, 0, QModelIndex()).isValid())
self.assertEqual(
model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole),
'EPSG:3111 - GDA94 / Vicgrid')
self.assertIsNone(
model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole))
self.assertIsNone(
model.data(model.index(-1, 0, QModelIndex()), Qt.DisplayRole))
self.assertEqual(model.crs(model.index(0, 0, QModelIndex())),
QgsCoordinateReferenceSystem('EPSG:3111'))
# push a vertical crs
registry.pushRecent(QgsCoordinateReferenceSystem('ESRI:115851'))
self.assertEqual(model.rowCount(), 2)
self.assertTrue(model.index(0, 0, QModelIndex()).isValid())
self.assertTrue(model.index(1, 0, QModelIndex()).isValid())
self.assertFalse(model.index(2, 0, QModelIndex()).isValid())
self.assertEqual(
model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole),
'ESRI:115851 - SIRGAS-CON_DGF00P01')
self.assertEqual(
model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole),
'EPSG:3111 - GDA94 / Vicgrid')
self.assertIsNone(
model.data(model.index(2, 0, QModelIndex()), Qt.DisplayRole))
self.assertEqual(model.crs(model.index(0, 0, QModelIndex())),
QgsCoordinateReferenceSystem('ESRI:115851'))
self.assertEqual(model.crs(model.index(1, 0, QModelIndex())),
QgsCoordinateReferenceSystem('EPSG:3111'))
# add filter
model.setFilters(QgsRecentCoordinateReferenceSystemsProxyModel.Filter.FilterHorizontal)
self.assertEqual(model.rowCount(), 1)
self.assertTrue(model.index(0, 0, QModelIndex()).isValid())
self.assertFalse(model.index(1, 0, QModelIndex()).isValid())
self.assertEqual(
model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole),
'EPSG:3111 - GDA94 / Vicgrid')
self.assertIsNone(
model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole))
self.assertEqual(model.crs(model.index(0, 0, QModelIndex())),
QgsCoordinateReferenceSystem('EPSG:3111'))
model.setFilters(QgsRecentCoordinateReferenceSystemsProxyModel.Filter.FilterVertical)
self.assertEqual(model.rowCount(), 1)
self.assertTrue(model.index(0, 0, QModelIndex()).isValid())
self.assertFalse(model.index(1, 0, QModelIndex()).isValid())
self.assertEqual(
model.data(model.index(0, 0, QModelIndex()), Qt.DisplayRole),
'ESRI:115851 - SIRGAS-CON_DGF00P01')
self.assertIsNone(
model.data(model.index(1, 0, QModelIndex()), Qt.DisplayRole))
self.assertEqual(model.crs(model.index(0, 0, QModelIndex())),
QgsCoordinateReferenceSystem('ESRI:115851'))
if __name__ == '__main__':
unittest.main()