mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-06 00:07:29 -04:00
Create a QAbstractItemModel and proxy model for displaying tree
view of coordinate reference systems
This commit is contained in:
parent
ce95f9a522
commit
731123a425
@ -0,0 +1,3 @@
|
|||||||
|
# The following has been generated automatically from src/gui/qgscoordinatereferencesystemmodel.h
|
||||||
|
QgsCoordinateReferenceSystemProxyModel.Filters.baseClass = QgsCoordinateReferenceSystemProxyModel
|
||||||
|
Filters = QgsCoordinateReferenceSystemProxyModel # dirty hack since SIP seems to introduce the flags in module
|
@ -0,0 +1,172 @@
|
|||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/gui/qgscoordinatereferencesystemmodel.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class QgsCoordinateReferenceSystemModel : QAbstractItemModel
|
||||||
|
{
|
||||||
|
%Docstring(signature="appended")
|
||||||
|
A tree model for display of known coordinate reference systems.
|
||||||
|
|
||||||
|
.. versionadded:: 3.34
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgscoordinatereferencesystemmodel.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Roles
|
||||||
|
{
|
||||||
|
RoleNodeType,
|
||||||
|
RoleName,
|
||||||
|
RoleAuthId,
|
||||||
|
RoleDeprecated,
|
||||||
|
RoleType,
|
||||||
|
RoleGroupId,
|
||||||
|
RoleWkt,
|
||||||
|
RoleProj,
|
||||||
|
};
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModel( QObject *parent = 0 );
|
||||||
|
|
||||||
|
virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
|
||||||
|
|
||||||
|
virtual QVariant data( const QModelIndex &index, int role ) const;
|
||||||
|
|
||||||
|
virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
|
||||||
|
|
||||||
|
virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const;
|
||||||
|
|
||||||
|
virtual int columnCount( const QModelIndex & = QModelIndex() ) const;
|
||||||
|
|
||||||
|
virtual QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const;
|
||||||
|
|
||||||
|
virtual QModelIndex parent( const QModelIndex &index ) const;
|
||||||
|
|
||||||
|
|
||||||
|
void addCustomCrs( const QgsCoordinateReferenceSystem &crs );
|
||||||
|
%Docstring
|
||||||
|
Adds a custom ``crs`` to the model.
|
||||||
|
|
||||||
|
This method can be used to add CRS which aren't present in either the standard PROJ SRS database or the
|
||||||
|
user's custom CRS database to the model.
|
||||||
|
%End
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class QgsCoordinateReferenceSystemProxyModel: QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
%Docstring(signature="appended")
|
||||||
|
A sort/filter proxy model for coordinate reference systems.
|
||||||
|
|
||||||
|
.. versionadded:: 3.34
|
||||||
|
%End
|
||||||
|
|
||||||
|
%TypeHeaderCode
|
||||||
|
#include "qgscoordinatereferencesystemmodel.h"
|
||||||
|
%End
|
||||||
|
public:
|
||||||
|
|
||||||
|
enum Filter
|
||||||
|
{
|
||||||
|
FilterHorizontal,
|
||||||
|
FilterVertical,
|
||||||
|
FilterCompound,
|
||||||
|
};
|
||||||
|
typedef QFlags<QgsCoordinateReferenceSystemProxyModel::Filter> Filters;
|
||||||
|
|
||||||
|
|
||||||
|
explicit QgsCoordinateReferenceSystemProxyModel( QObject *parent /TransferThis/ = 0 );
|
||||||
|
%Docstring
|
||||||
|
Constructor for QgsCoordinateReferenceSystemProxyModel, with the given ``parent`` object.
|
||||||
|
%End
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModel *coordinateReferenceSystemModel();
|
||||||
|
%Docstring
|
||||||
|
Returns the underlying source model.
|
||||||
|
%End
|
||||||
|
|
||||||
|
|
||||||
|
void setFilters( QgsCoordinateReferenceSystemProxyModel::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
|
||||||
|
|
||||||
|
void setFilterString( const QString &filter );
|
||||||
|
%Docstring
|
||||||
|
Sets a ``filter`` string, such that only coordinate reference systems matching the
|
||||||
|
specified string will be shown.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`filterString`
|
||||||
|
%End
|
||||||
|
|
||||||
|
QString filterString() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the current filter string, if set.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`setFilterString`
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setFilterAuthIds( const QStringList &filter );
|
||||||
|
%Docstring
|
||||||
|
Sets a ``filter`` list of CRS auth ID strings, such that only coordinate reference systems matching the
|
||||||
|
specified auth IDs will be shown.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`filterAuthIds`
|
||||||
|
%End
|
||||||
|
|
||||||
|
QStringList filterAuthIds() const;
|
||||||
|
%Docstring
|
||||||
|
Returns the current filter list of auth ID strings, if set.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`setFilterString`
|
||||||
|
%End
|
||||||
|
|
||||||
|
void setFilterDeprecated( bool filter );
|
||||||
|
%Docstring
|
||||||
|
Sets whether deprecated CRS should be filtered from the results.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`filterDeprecated`
|
||||||
|
%End
|
||||||
|
|
||||||
|
bool filterDeprecated() const;
|
||||||
|
%Docstring
|
||||||
|
Returns whether deprecated CRS will be filtered from the results.
|
||||||
|
|
||||||
|
.. seealso:: :py:func:`setFilterDeprecated`
|
||||||
|
%End
|
||||||
|
|
||||||
|
virtual bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const;
|
||||||
|
|
||||||
|
virtual bool lessThan( const QModelIndex &left, const QModelIndex &right ) const;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* This file has been generated automatically from *
|
||||||
|
* *
|
||||||
|
* src/gui/qgscoordinatereferencesystemmodel.h *
|
||||||
|
* *
|
||||||
|
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||||
|
************************************************************************/
|
@ -38,6 +38,7 @@
|
|||||||
%Include auto_generated/qgsconfigureshortcutsdialog.sip
|
%Include auto_generated/qgsconfigureshortcutsdialog.sip
|
||||||
%Include auto_generated/qgscoordinateboundspreviewmapwidget.sip
|
%Include auto_generated/qgscoordinateboundspreviewmapwidget.sip
|
||||||
%Include auto_generated/qgscoordinateoperationwidget.sip
|
%Include auto_generated/qgscoordinateoperationwidget.sip
|
||||||
|
%Include auto_generated/qgscoordinatereferencesystemmodel.sip
|
||||||
%Include auto_generated/qgscredentialdialog.sip
|
%Include auto_generated/qgscredentialdialog.sip
|
||||||
%Include auto_generated/qgscrsdefinitionwidget.sip
|
%Include auto_generated/qgscrsdefinitionwidget.sip
|
||||||
%Include auto_generated/qgscurveeditorwidget.sip
|
%Include auto_generated/qgscurveeditorwidget.sip
|
||||||
|
@ -235,7 +235,7 @@ bool QgsCoordinateReferenceSystemRegistry::updateUserCrs( long id, const QgsCoor
|
|||||||
|
|
||||||
if ( res )
|
if ( res )
|
||||||
{
|
{
|
||||||
emit userCrsChanged( crs.d->mAuthId );
|
emit userCrsChanged( QStringLiteral( "USER:%1" ).arg( id ) );
|
||||||
emit crsDefinitionsChanged();
|
emit crsDefinitionsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,7 +446,7 @@ QList<QgsCrsDbRecord> QgsCoordinateReferenceSystemRegistry::crsDbRecords() const
|
|||||||
int result = database.open_v2( srsDatabaseFileName, SQLITE_OPEN_READONLY, nullptr );
|
int result = database.open_v2( srsDatabaseFileName, SQLITE_OPEN_READONLY, nullptr );
|
||||||
if ( result == SQLITE_OK )
|
if ( result == SQLITE_OK )
|
||||||
{
|
{
|
||||||
const QString sql = QStringLiteral( "select description, srs_id, auth_name, auth_id, name, deprecated, srs_type from vw_srs" );
|
const QString sql = QStringLiteral( "select description, srs_id, auth_name, auth_id, projection_acronym, deprecated, srs_type from tbl_srs" );
|
||||||
sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
|
sqlite3_statement_unique_ptr preparedStatement = database.prepare( sql, result );
|
||||||
if ( result == SQLITE_OK )
|
if ( result == SQLITE_OK )
|
||||||
{
|
{
|
||||||
@ -457,7 +457,7 @@ QList<QgsCrsDbRecord> QgsCoordinateReferenceSystemRegistry::crsDbRecords() const
|
|||||||
record.srsId = preparedStatement.columnAsText( 1 );
|
record.srsId = preparedStatement.columnAsText( 1 );
|
||||||
record.authName = preparedStatement.columnAsText( 2 );
|
record.authName = preparedStatement.columnAsText( 2 );
|
||||||
record.authId = preparedStatement.columnAsText( 3 );
|
record.authId = preparedStatement.columnAsText( 3 );
|
||||||
record.name = preparedStatement.columnAsText( 4 );
|
record.projectionAcronym = preparedStatement.columnAsText( 4 );
|
||||||
record.deprecated = preparedStatement.columnAsText( 5 ).toInt();
|
record.deprecated = preparedStatement.columnAsText( 5 ).toInt();
|
||||||
record.type = qgsEnumKeyToValue( preparedStatement.columnAsText( 6 ), Qgis::CrsType::Unknown );
|
record.type = qgsEnumKeyToValue( preparedStatement.columnAsText( 6 ), Qgis::CrsType::Unknown );
|
||||||
mCrsDbRecords.append( record );
|
mCrsDbRecords.append( record );
|
||||||
|
@ -41,7 +41,7 @@ class QgsProjOperation;
|
|||||||
struct CORE_EXPORT QgsCrsDbRecord
|
struct CORE_EXPORT QgsCrsDbRecord
|
||||||
{
|
{
|
||||||
QString description;
|
QString description;
|
||||||
QString name;
|
QString projectionAcronym;
|
||||||
QString srsId;
|
QString srsId;
|
||||||
QString authName;
|
QString authName;
|
||||||
QString authId;
|
QString authId;
|
||||||
|
@ -515,6 +515,7 @@ set(QGIS_GUI_SRCS
|
|||||||
qgsconfigureshortcutsdialog.cpp
|
qgsconfigureshortcutsdialog.cpp
|
||||||
qgscoordinateboundspreviewmapwidget.cpp
|
qgscoordinateboundspreviewmapwidget.cpp
|
||||||
qgscoordinateoperationwidget.cpp
|
qgscoordinateoperationwidget.cpp
|
||||||
|
qgscoordinatereferencesystemmodel.cpp
|
||||||
qgscrsdefinitionwidget.cpp
|
qgscrsdefinitionwidget.cpp
|
||||||
qgscredentialdialog.cpp
|
qgscredentialdialog.cpp
|
||||||
qgscustomdrophandler.cpp
|
qgscustomdrophandler.cpp
|
||||||
@ -786,6 +787,7 @@ set(QGIS_GUI_HDRS
|
|||||||
qgsconfigureshortcutsdialog.h
|
qgsconfigureshortcutsdialog.h
|
||||||
qgscoordinateboundspreviewmapwidget.h
|
qgscoordinateboundspreviewmapwidget.h
|
||||||
qgscoordinateoperationwidget.h
|
qgscoordinateoperationwidget.h
|
||||||
|
qgscoordinatereferencesystemmodel.h
|
||||||
qgscredentialdialog.h
|
qgscredentialdialog.h
|
||||||
qgscrsdefinitionwidget.h
|
qgscrsdefinitionwidget.h
|
||||||
qgscurveeditorwidget.h
|
qgscurveeditorwidget.h
|
||||||
|
739
src/gui/qgscoordinatereferencesystemmodel.cpp
Normal file
739
src/gui/qgscoordinatereferencesystemmodel.cpp
Normal file
@ -0,0 +1,739 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgscoordinatereferencesystemmodel.h
|
||||||
|
-------------------
|
||||||
|
begin : July 2023
|
||||||
|
copyright : (C) 2023 by Nyall Dawson
|
||||||
|
email : nyall dot dawson at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
#include "qgscoordinatereferencesystemmodel.h"
|
||||||
|
#include "qgscoordinatereferencesystemutils.h"
|
||||||
|
#include "qgsapplication.h"
|
||||||
|
|
||||||
|
#include <QFont>
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModel::QgsCoordinateReferenceSystemModel( QObject *parent )
|
||||||
|
: QAbstractItemModel( parent )
|
||||||
|
, mRootNode( std::make_unique< QgsCoordinateReferenceSystemModelGroupNode >( QString(), QIcon(), QString() ) )
|
||||||
|
{
|
||||||
|
mCrsDbRecords = QgsApplication::coordinateReferenceSystemRegistry()->crsDbRecords();
|
||||||
|
|
||||||
|
rebuild();
|
||||||
|
|
||||||
|
connect( QgsApplication::coordinateReferenceSystemRegistry(), &QgsCoordinateReferenceSystemRegistry::userCrsAdded, this, &QgsCoordinateReferenceSystemModel::userCrsAdded );
|
||||||
|
connect( QgsApplication::coordinateReferenceSystemRegistry(), &QgsCoordinateReferenceSystemRegistry::userCrsRemoved, this, &QgsCoordinateReferenceSystemModel::userCrsRemoved );
|
||||||
|
connect( QgsApplication::coordinateReferenceSystemRegistry(), &QgsCoordinateReferenceSystemRegistry::userCrsChanged, this, &QgsCoordinateReferenceSystemModel::userCrsChanged );
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags QgsCoordinateReferenceSystemModel::flags( const QModelIndex &index ) const
|
||||||
|
{
|
||||||
|
if ( !index.isValid() )
|
||||||
|
{
|
||||||
|
return Qt::ItemFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelNode *n = index2node( index );
|
||||||
|
if ( !n )
|
||||||
|
return Qt::ItemFlags();
|
||||||
|
|
||||||
|
switch ( n->nodeType() )
|
||||||
|
{
|
||||||
|
case QgsCoordinateReferenceSystemModelNode::NodeGroup:
|
||||||
|
return index.column() == 0 ? Qt::ItemIsEnabled : Qt::ItemFlags();
|
||||||
|
case QgsCoordinateReferenceSystemModelNode::NodeCrs:
|
||||||
|
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||||
|
}
|
||||||
|
BUILTIN_UNREACHABLE
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant QgsCoordinateReferenceSystemModel::data( const QModelIndex &index, int role ) const
|
||||||
|
{
|
||||||
|
if ( !index.isValid() )
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelNode *n = index2node( index );
|
||||||
|
if ( !n )
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
if ( role == RoleNodeType )
|
||||||
|
return n->nodeType();
|
||||||
|
|
||||||
|
switch ( n->nodeType() )
|
||||||
|
{
|
||||||
|
case QgsCoordinateReferenceSystemModelNode::NodeGroup:
|
||||||
|
{
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode *groupNode = qgis::down_cast< QgsCoordinateReferenceSystemModelGroupNode * >( n );
|
||||||
|
switch ( role )
|
||||||
|
{
|
||||||
|
case Qt::DecorationRole:
|
||||||
|
switch ( index.column() )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return groupNode->icon();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::ToolTipRole:
|
||||||
|
switch ( index.column() )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return groupNode->name();
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qt::FontRole:
|
||||||
|
{
|
||||||
|
QFont font;
|
||||||
|
font.setItalic( true );
|
||||||
|
if ( groupNode->parent() == mRootNode.get() )
|
||||||
|
{
|
||||||
|
font.setBold( true );
|
||||||
|
}
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
case RoleGroupId:
|
||||||
|
return groupNode->id();
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
}
|
||||||
|
case QgsCoordinateReferenceSystemModelNode::NodeCrs:
|
||||||
|
{
|
||||||
|
QgsCoordinateReferenceSystemModelCrsNode *crsNode = qgis::down_cast< QgsCoordinateReferenceSystemModelCrsNode * >( n );
|
||||||
|
switch ( role )
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
case Qt::ToolTipRole:
|
||||||
|
switch ( index.column() )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return crsNode->record().description;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
if ( crsNode->record().authName == QLatin1String( "CUSTOM" ) )
|
||||||
|
return QString();
|
||||||
|
return QStringLiteral( "%1:%2" ).arg( crsNode->record().authName, crsNode->record().authId );
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RoleName:
|
||||||
|
return crsNode->record().description;
|
||||||
|
|
||||||
|
case RoleAuthId:
|
||||||
|
return QStringLiteral( "%1:%2" ).arg( crsNode->record().authName, crsNode->record().authId );
|
||||||
|
|
||||||
|
case RoleDeprecated:
|
||||||
|
return crsNode->record().deprecated;
|
||||||
|
|
||||||
|
case RoleType:
|
||||||
|
return QVariant::fromValue( crsNode->record().type );
|
||||||
|
|
||||||
|
case RoleWkt:
|
||||||
|
return crsNode->wkt();
|
||||||
|
|
||||||
|
case RoleProj:
|
||||||
|
return crsNode->proj();
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant QgsCoordinateReferenceSystemModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
||||||
|
{
|
||||||
|
if ( orientation == Qt::Horizontal )
|
||||||
|
{
|
||||||
|
switch ( role )
|
||||||
|
{
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch ( section )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return tr( "Coordinate Reference System" );
|
||||||
|
case 1:
|
||||||
|
return tr( "Authority ID" );
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsCoordinateReferenceSystemModel::rowCount( const QModelIndex &parent ) const
|
||||||
|
{
|
||||||
|
QgsCoordinateReferenceSystemModelNode *n = index2node( parent );
|
||||||
|
if ( !n )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return n->children().count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QgsCoordinateReferenceSystemModel::columnCount( const QModelIndex & ) const
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex QgsCoordinateReferenceSystemModel::index( int row, int column, const QModelIndex &parent ) const
|
||||||
|
{
|
||||||
|
if ( !hasIndex( row, column, parent ) )
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelNode *n = index2node( parent );
|
||||||
|
if ( !n )
|
||||||
|
return QModelIndex(); // have no children
|
||||||
|
|
||||||
|
return createIndex( row, column, n->children().at( row ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex QgsCoordinateReferenceSystemModel::parent( const QModelIndex &child ) const
|
||||||
|
{
|
||||||
|
if ( !child.isValid() )
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
if ( QgsCoordinateReferenceSystemModelNode *n = index2node( child ) )
|
||||||
|
{
|
||||||
|
return indexOfParentTreeNode( n->parent() ); // must not be null
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Q_ASSERT( false ); // no other node types!
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemModel::rebuild()
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
|
||||||
|
mRootNode->deleteChildren();
|
||||||
|
|
||||||
|
for ( const QgsCrsDbRecord &record : std::as_const( mCrsDbRecords ) )
|
||||||
|
{
|
||||||
|
addRecord( record );
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<QgsCoordinateReferenceSystemRegistry::UserCrsDetails> userCrsList = QgsApplication::coordinateReferenceSystemRegistry()->userCrsList();
|
||||||
|
for ( const QgsCoordinateReferenceSystemRegistry::UserCrsDetails &details : userCrsList )
|
||||||
|
{
|
||||||
|
QgsCrsDbRecord userRecord;
|
||||||
|
userRecord.authName = QStringLiteral( "USER" );
|
||||||
|
userRecord.authId = QString::number( details.id );
|
||||||
|
userRecord.description = details.name;
|
||||||
|
|
||||||
|
addRecord( userRecord );
|
||||||
|
}
|
||||||
|
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemModel::userCrsAdded( const QString &id )
|
||||||
|
{
|
||||||
|
const QList<QgsCoordinateReferenceSystemRegistry::UserCrsDetails> userCrsList = QgsApplication::coordinateReferenceSystemRegistry()->userCrsList();
|
||||||
|
for ( const QgsCoordinateReferenceSystemRegistry::UserCrsDetails &details : userCrsList )
|
||||||
|
{
|
||||||
|
if ( QStringLiteral( "USER:%1" ).arg( details.id ) == id )
|
||||||
|
{
|
||||||
|
QgsCrsDbRecord userRecord;
|
||||||
|
userRecord.authName = QStringLiteral( "USER" );
|
||||||
|
userRecord.authId = QString::number( details.id );
|
||||||
|
userRecord.description = details.name;
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( "USER" ) );
|
||||||
|
if ( !group )
|
||||||
|
{
|
||||||
|
std::unique_ptr< QgsCoordinateReferenceSystemModelGroupNode > newGroup = std::make_unique< QgsCoordinateReferenceSystemModelGroupNode >(
|
||||||
|
tr( "User Defined Coordinate Systems" ),
|
||||||
|
QgsApplication::getThemeIcon( QStringLiteral( "/user.svg" ) ), QStringLiteral( "USER" ) );
|
||||||
|
beginInsertRows( QModelIndex(), mRootNode->children().length(), mRootNode->children().length() );
|
||||||
|
mRootNode->addChildNode( newGroup.get() );
|
||||||
|
endInsertRows();
|
||||||
|
group = newGroup.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QModelIndex parentGroupIndex = node2index( group );
|
||||||
|
|
||||||
|
beginInsertRows( parentGroupIndex, group->children().size(), group->children().size() );
|
||||||
|
QgsCoordinateReferenceSystemModelCrsNode *crsNode = addRecord( userRecord );
|
||||||
|
crsNode->setProj( details.proj );
|
||||||
|
crsNode->setWkt( details.wkt );
|
||||||
|
endInsertRows();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemModel::userCrsRemoved( long id )
|
||||||
|
{
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( "USER" ) );
|
||||||
|
if ( group )
|
||||||
|
{
|
||||||
|
for ( int row = 0; row < group->children().size(); ++row )
|
||||||
|
{
|
||||||
|
if ( QgsCoordinateReferenceSystemModelCrsNode *crsNode = dynamic_cast< QgsCoordinateReferenceSystemModelCrsNode * >( group->children().at( row ) ) )
|
||||||
|
{
|
||||||
|
if ( crsNode->record().authId == QString::number( id ) )
|
||||||
|
{
|
||||||
|
const QModelIndex parentIndex = node2index( group );
|
||||||
|
beginRemoveRows( parentIndex, row, row );
|
||||||
|
delete group->takeChild( crsNode );
|
||||||
|
endRemoveRows();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemModel::userCrsChanged( const QString &id )
|
||||||
|
{
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( "USER" ) );
|
||||||
|
if ( group )
|
||||||
|
{
|
||||||
|
for ( int row = 0; row < group->children().size(); ++row )
|
||||||
|
{
|
||||||
|
if ( QgsCoordinateReferenceSystemModelCrsNode *crsNode = dynamic_cast< QgsCoordinateReferenceSystemModelCrsNode * >( group->children().at( row ) ) )
|
||||||
|
{
|
||||||
|
if ( QStringLiteral( "USER:%1" ).arg( crsNode->record().authId ) == id )
|
||||||
|
{
|
||||||
|
// treat a change as a remove + add operation
|
||||||
|
const QModelIndex parentIndex = node2index( group );
|
||||||
|
beginRemoveRows( parentIndex, row, row );
|
||||||
|
delete group->takeChild( crsNode );
|
||||||
|
endRemoveRows();
|
||||||
|
|
||||||
|
userCrsAdded( id );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelCrsNode *QgsCoordinateReferenceSystemModel::addRecord( const QgsCrsDbRecord &record )
|
||||||
|
{
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode *parentNode = mRootNode.get();
|
||||||
|
std::unique_ptr< QgsCoordinateReferenceSystemModelCrsNode > crsNode = std::make_unique< QgsCoordinateReferenceSystemModelCrsNode>( record );
|
||||||
|
|
||||||
|
QString groupName;
|
||||||
|
QString groupId;
|
||||||
|
QIcon groupIcon;
|
||||||
|
if ( record.authName == QLatin1String( "USER" ) )
|
||||||
|
{
|
||||||
|
groupName = tr( "User Defined Coordinate Systems" );
|
||||||
|
groupId = QStringLiteral( "USER" );
|
||||||
|
groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/user.svg" ) );
|
||||||
|
}
|
||||||
|
else if ( record.authName == QLatin1String( "CUSTOM" ) )
|
||||||
|
{
|
||||||
|
// the group is guaranteed to exist at this point
|
||||||
|
groupId = QStringLiteral( "CUSTOM" );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
groupId = qgsEnumValueToKey( record.type );
|
||||||
|
switch ( record.type )
|
||||||
|
{
|
||||||
|
case Qgis::CrsType::Unknown:
|
||||||
|
break;
|
||||||
|
case Qgis::CrsType::Geodetic:
|
||||||
|
groupName = tr( "Geodetic" );
|
||||||
|
groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconProjectionEnabled.svg" ) );
|
||||||
|
break;
|
||||||
|
case Qgis::CrsType::Geocentric:
|
||||||
|
groupName = tr( "Geocentric" );
|
||||||
|
groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconProjectionEnabled.svg" ) );
|
||||||
|
break;
|
||||||
|
case Qgis::CrsType::Geographic2d:
|
||||||
|
groupName = tr( "Geographic (2D)" );
|
||||||
|
groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconProjectionEnabled.svg" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qgis::CrsType::Geographic3d:
|
||||||
|
groupName = tr( "Geographic (3D)" );
|
||||||
|
groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconProjectionEnabled.svg" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qgis::CrsType::Vertical:
|
||||||
|
groupName = tr( "Vertical" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qgis::CrsType::Projected:
|
||||||
|
case Qgis::CrsType::DerivedProjected:
|
||||||
|
groupName = tr( "Projected" );
|
||||||
|
groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/transformed.svg" ) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qgis::CrsType::Compound:
|
||||||
|
groupName = tr( "Compound" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qgis::CrsType::Temporal:
|
||||||
|
groupName = tr( "Temporal" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qgis::CrsType::Engineering:
|
||||||
|
groupName = tr( "Engineering" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qgis::CrsType::Bound:
|
||||||
|
groupName = tr( "Bound" );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Qgis::CrsType::Other:
|
||||||
|
groupName = tr( "Other" );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( QgsCoordinateReferenceSystemModelGroupNode *group = parentNode->getChildGroupNode( groupId ) )
|
||||||
|
{
|
||||||
|
parentNode = group;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::unique_ptr< QgsCoordinateReferenceSystemModelGroupNode > newGroup = std::make_unique< QgsCoordinateReferenceSystemModelGroupNode >( groupName, groupIcon, groupId );
|
||||||
|
parentNode->addChildNode( newGroup.get() );
|
||||||
|
parentNode = newGroup.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( record.authName != QLatin1String( "USER" ) && record.authName != QLatin1String( "CUSTOM" ) ) && ( record.type == Qgis::CrsType::Projected || record.type == Qgis::CrsType::DerivedProjected ) )
|
||||||
|
{
|
||||||
|
QString projectionName = QgsCoordinateReferenceSystemUtils::translateProjection( record.projectionAcronym );
|
||||||
|
if ( projectionName.isEmpty() )
|
||||||
|
projectionName = tr( "Other" );
|
||||||
|
|
||||||
|
if ( QgsCoordinateReferenceSystemModelGroupNode *group = parentNode->getChildGroupNode( record.projectionAcronym ) )
|
||||||
|
{
|
||||||
|
parentNode = group;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::unique_ptr< QgsCoordinateReferenceSystemModelGroupNode > newGroup = std::make_unique< QgsCoordinateReferenceSystemModelGroupNode >( projectionName, QIcon(), record.projectionAcronym );
|
||||||
|
parentNode->addChildNode( newGroup.get() );
|
||||||
|
parentNode = newGroup.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parentNode->addChildNode( crsNode.get() );
|
||||||
|
return crsNode.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemModel::addCustomCrs( const QgsCoordinateReferenceSystem &crs )
|
||||||
|
{
|
||||||
|
QgsCrsDbRecord userRecord;
|
||||||
|
userRecord.authName = QStringLiteral( "CUSTOM" );
|
||||||
|
userRecord.description = crs.description().isEmpty() ? tr( "Custom CRS" ) : crs.description();
|
||||||
|
userRecord.type = crs.type();
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( "CUSTOM" ) );
|
||||||
|
if ( !group )
|
||||||
|
{
|
||||||
|
std::unique_ptr< QgsCoordinateReferenceSystemModelGroupNode > newGroup = std::make_unique< QgsCoordinateReferenceSystemModelGroupNode >(
|
||||||
|
tr( "Custom Coordinate Systems" ),
|
||||||
|
QgsApplication::getThemeIcon( QStringLiteral( "/user.svg" ) ), QStringLiteral( "CUSTOM" ) );
|
||||||
|
beginInsertRows( QModelIndex(), mRootNode->children().length(), mRootNode->children().length() );
|
||||||
|
mRootNode->addChildNode( newGroup.get() );
|
||||||
|
endInsertRows();
|
||||||
|
group = newGroup.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QModelIndex parentGroupIndex = node2index( group );
|
||||||
|
|
||||||
|
beginInsertRows( parentGroupIndex, group->children().size(), group->children().size() );
|
||||||
|
QgsCoordinateReferenceSystemModelCrsNode *node = addRecord( userRecord );
|
||||||
|
node->setWkt( crs.toWkt( QgsCoordinateReferenceSystem::WKT_PREFERRED ) );
|
||||||
|
node->setProj( crs.toProj() );
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelNode *QgsCoordinateReferenceSystemModel::index2node( const QModelIndex &index ) const
|
||||||
|
{
|
||||||
|
if ( !index.isValid() )
|
||||||
|
return mRootNode.get();
|
||||||
|
|
||||||
|
return reinterpret_cast<QgsCoordinateReferenceSystemModelNode *>( index.internalPointer() );
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex QgsCoordinateReferenceSystemModel::node2index( QgsCoordinateReferenceSystemModelNode *node ) const
|
||||||
|
{
|
||||||
|
if ( !node || !node->parent() )
|
||||||
|
return QModelIndex(); // this is the only root item -> invalid index
|
||||||
|
|
||||||
|
QModelIndex parentIndex = node2index( node->parent() );
|
||||||
|
|
||||||
|
int row = node->parent()->children().indexOf( node );
|
||||||
|
Q_ASSERT( row >= 0 );
|
||||||
|
return index( row, 0, parentIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex QgsCoordinateReferenceSystemModel::indexOfParentTreeNode( QgsCoordinateReferenceSystemModelNode *parentNode ) const
|
||||||
|
{
|
||||||
|
Q_ASSERT( parentNode );
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelNode *grandParentNode = parentNode->parent();
|
||||||
|
if ( !grandParentNode )
|
||||||
|
return QModelIndex(); // root node -> invalid index
|
||||||
|
|
||||||
|
int row = grandParentNode->children().indexOf( parentNode );
|
||||||
|
Q_ASSERT( row >= 0 );
|
||||||
|
|
||||||
|
return createIndex( row, 0, parentNode );
|
||||||
|
}
|
||||||
|
|
||||||
|
///@cond PRIVATE
|
||||||
|
QgsCoordinateReferenceSystemModelNode::~QgsCoordinateReferenceSystemModelNode() = default;
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelNode *QgsCoordinateReferenceSystemModelNode::takeChild( QgsCoordinateReferenceSystemModelNode *node )
|
||||||
|
{
|
||||||
|
return mChildren.takeAt( mChildren.indexOf( node ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemModelNode::addChildNode( QgsCoordinateReferenceSystemModelNode *node )
|
||||||
|
{
|
||||||
|
if ( !node )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Q_ASSERT( !node->mParent );
|
||||||
|
node->mParent = this;
|
||||||
|
|
||||||
|
mChildren.append( node );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemModelNode::deleteChildren()
|
||||||
|
{
|
||||||
|
qDeleteAll( mChildren );
|
||||||
|
mChildren.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode *QgsCoordinateReferenceSystemModelNode::getChildGroupNode( const QString &id )
|
||||||
|
{
|
||||||
|
for ( QgsCoordinateReferenceSystemModelNode *node : std::as_const( mChildren ) )
|
||||||
|
{
|
||||||
|
if ( node->nodeType() == NodeGroup )
|
||||||
|
{
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode *groupNode = qgis::down_cast< QgsCoordinateReferenceSystemModelGroupNode * >( node );
|
||||||
|
if ( groupNode && groupNode->id() == id )
|
||||||
|
return groupNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode::QgsCoordinateReferenceSystemModelGroupNode( const QString &name, const QIcon &icon, const QString &id )
|
||||||
|
: mId( id )
|
||||||
|
, mName( name )
|
||||||
|
, mIcon( icon )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelCrsNode::QgsCoordinateReferenceSystemModelCrsNode( const QgsCrsDbRecord &record )
|
||||||
|
: mRecord( record )
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
///@endcond
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// QgsCoordinateReferenceSystemProxyModel
|
||||||
|
//
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemProxyModel::QgsCoordinateReferenceSystemProxyModel( QObject *parent )
|
||||||
|
: QSortFilterProxyModel( parent )
|
||||||
|
, mModel( new QgsCoordinateReferenceSystemModel( this ) )
|
||||||
|
{
|
||||||
|
setSourceModel( mModel );
|
||||||
|
setDynamicSortFilter( true );
|
||||||
|
setSortLocaleAware( true );
|
||||||
|
setFilterCaseSensitivity( Qt::CaseInsensitive );
|
||||||
|
setRecursiveFilteringEnabled( true );
|
||||||
|
sort( 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModel *QgsCoordinateReferenceSystemProxyModel::coordinateReferenceSystemModel()
|
||||||
|
{
|
||||||
|
return mModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QgsCoordinateReferenceSystemModel *QgsCoordinateReferenceSystemProxyModel::coordinateReferenceSystemModel() const
|
||||||
|
{
|
||||||
|
return mModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemProxyModel::setFilters( QgsCoordinateReferenceSystemProxyModel::Filters filters )
|
||||||
|
{
|
||||||
|
if ( mFilters == filters )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mFilters = filters;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemProxyModel::setFilterString( const QString &filter )
|
||||||
|
{
|
||||||
|
mFilterString = filter;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemProxyModel::setFilterAuthIds( const QStringList &filter )
|
||||||
|
{
|
||||||
|
if ( mFilterAuthIds == filter )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mFilterAuthIds.clear();
|
||||||
|
mFilterAuthIds.reserve( filter.size() );
|
||||||
|
for ( const QString &id : filter )
|
||||||
|
{
|
||||||
|
mFilterAuthIds.insert( id.toUpper() );
|
||||||
|
}
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsCoordinateReferenceSystemProxyModel::setFilterDeprecated( bool filter )
|
||||||
|
{
|
||||||
|
if ( mFilterDeprecated == filter )
|
||||||
|
return;
|
||||||
|
|
||||||
|
mFilterDeprecated = filter;
|
||||||
|
invalidateFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsCoordinateReferenceSystemProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
|
||||||
|
{
|
||||||
|
if ( mFilterString.trimmed().isEmpty() && !mFilters && !mFilterDeprecated && mFilterAuthIds.isEmpty() )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
|
||||||
|
const QgsCoordinateReferenceSystemModelNode::NodeType nodeType = static_cast< QgsCoordinateReferenceSystemModelNode::NodeType >( sourceModel()->data( sourceIndex, QgsCoordinateReferenceSystemModel::RoleNodeType ).toInt() );
|
||||||
|
switch ( nodeType )
|
||||||
|
{
|
||||||
|
case QgsCoordinateReferenceSystemModelNode::NodeGroup:
|
||||||
|
return false;
|
||||||
|
case QgsCoordinateReferenceSystemModelNode::NodeCrs:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool deprecated = sourceModel()->data( sourceIndex, QgsCoordinateReferenceSystemModel::RoleDeprecated ).toBool();
|
||||||
|
if ( mFilterDeprecated && deprecated )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( mFilters )
|
||||||
|
{
|
||||||
|
const Qgis::CrsType type = sourceModel()->data( sourceIndex, QgsCoordinateReferenceSystemModel::RoleType ).value< Qgis::CrsType >();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString authid = sourceModel()->data( sourceIndex, QgsCoordinateReferenceSystemModel::RoleAuthId ).toString();
|
||||||
|
if ( !mFilterAuthIds.isEmpty() )
|
||||||
|
{
|
||||||
|
if ( !mFilterAuthIds.contains( authid.toUpper() ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !mFilterString.trimmed().isEmpty() )
|
||||||
|
{
|
||||||
|
const QString name = sourceModel()->data( sourceIndex, QgsCoordinateReferenceSystemModel::RoleName ).toString();
|
||||||
|
if ( !( name.contains( mFilterString, Qt::CaseInsensitive )
|
||||||
|
|| authid.contains( mFilterString, Qt::CaseInsensitive ) ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsCoordinateReferenceSystemProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
|
||||||
|
{
|
||||||
|
QgsCoordinateReferenceSystemModelNode::NodeType leftType = static_cast< QgsCoordinateReferenceSystemModelNode::NodeType >( sourceModel()->data( left, QgsCoordinateReferenceSystemModel::RoleNodeType ).toInt() );
|
||||||
|
QgsCoordinateReferenceSystemModelNode::NodeType rightType = static_cast< QgsCoordinateReferenceSystemModelNode::NodeType >( sourceModel()->data( right, QgsCoordinateReferenceSystemModel::RoleNodeType ).toInt() );
|
||||||
|
|
||||||
|
if ( leftType != rightType )
|
||||||
|
{
|
||||||
|
if ( leftType == QgsCoordinateReferenceSystemModelNode::NodeGroup )
|
||||||
|
return true;
|
||||||
|
else if ( rightType == QgsCoordinateReferenceSystemModelNode::NodeGroup )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString leftStr = sourceModel()->data( left ).toString().toLower();
|
||||||
|
const QString rightStr = sourceModel()->data( right ).toString().toLower();
|
||||||
|
|
||||||
|
if ( leftType == QgsCoordinateReferenceSystemModelNode::NodeGroup )
|
||||||
|
{
|
||||||
|
// both are groups -- ensure USER group comes last, and CUSTOM group comes first
|
||||||
|
const QString leftGroupId = sourceModel()->data( left, QgsCoordinateReferenceSystemModel::RoleGroupId ).toString();
|
||||||
|
const QString rightGroupId = sourceModel()->data( left, QgsCoordinateReferenceSystemModel::RoleGroupId ).toString();
|
||||||
|
if ( leftGroupId == QLatin1String( "USER" ) )
|
||||||
|
return false;
|
||||||
|
if ( rightGroupId == QLatin1String( "USER" ) )
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if ( leftGroupId == QLatin1String( "CUSTOM" ) )
|
||||||
|
return true;
|
||||||
|
if ( rightGroupId == QLatin1String( "CUSTOM" ) )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// default sort is alphabetical order
|
||||||
|
return QString::localeAwareCompare( leftStr, rightStr ) < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
391
src/gui/qgscoordinatereferencesystemmodel.h
Normal file
391
src/gui/qgscoordinatereferencesystemmodel.h
Normal file
@ -0,0 +1,391 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgscoordinatereferencesystemmodel.h
|
||||||
|
-------------------
|
||||||
|
begin : July 2023
|
||||||
|
copyright : (C) 2023 by Nyall Dawson
|
||||||
|
email : nyall dot dawson at gmail dot com
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* *
|
||||||
|
* 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. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef QGSCOORDINATEREFERENCESYSTEMMODEL_H
|
||||||
|
#define QGSCOORDINATEREFERENCESYSTEMMODEL_H
|
||||||
|
|
||||||
|
#include "qgis_gui.h"
|
||||||
|
#include "qgis_sip.h"
|
||||||
|
#include "qgis.h"
|
||||||
|
#include "qgscoordinatereferencesystemregistry.h"
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <QIcon>
|
||||||
|
|
||||||
|
class QgsCoordinateReferenceSystem;
|
||||||
|
class QgsCoordinateReferenceSystemModelGroupNode;
|
||||||
|
|
||||||
|
///@cond PRIVATE
|
||||||
|
#ifndef SIP_RUN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Abstract base class for nodes contained within a QgsCoordinateReferenceSystemModel.
|
||||||
|
* \warning Not part of stable API and may change in future QGIS releases.
|
||||||
|
* \ingroup gui
|
||||||
|
* \since QGIS 3.34
|
||||||
|
*/
|
||||||
|
class GUI_EXPORT QgsCoordinateReferenceSystemModelNode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Enumeration of possible model node types
|
||||||
|
enum NodeType
|
||||||
|
{
|
||||||
|
NodeGroup, //!< Group node
|
||||||
|
NodeCrs, //!< CRS node
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~QgsCoordinateReferenceSystemModelNode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node's type.
|
||||||
|
*/
|
||||||
|
virtual NodeType nodeType() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the node's parent. If the node's parent is NULLPTR, then the node is a root node.
|
||||||
|
*/
|
||||||
|
QgsCoordinateReferenceSystemModelNode *parent() { return mParent; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of children belonging to the node.
|
||||||
|
*/
|
||||||
|
QList<QgsCoordinateReferenceSystemModelNode *> children() { return mChildren; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a list of children belonging to the node.
|
||||||
|
*/
|
||||||
|
QList<QgsCoordinateReferenceSystemModelNode *> children() const { return mChildren; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the specified \a node from this node's children, and gives
|
||||||
|
* ownership back to the caller.
|
||||||
|
*/
|
||||||
|
QgsCoordinateReferenceSystemModelNode *takeChild( QgsCoordinateReferenceSystemModelNode *node );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a child \a node to this node, transferring ownership of the node
|
||||||
|
* to this node.
|
||||||
|
*/
|
||||||
|
void addChildNode( QgsCoordinateReferenceSystemModelNode *node );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all child nodes from this node.
|
||||||
|
*/
|
||||||
|
void deleteChildren();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tries to find a child node belonging to this node, which corresponds to
|
||||||
|
* a group node with the given group \a id. Returns NULLPTR if no matching
|
||||||
|
* child group node was found.
|
||||||
|
*/
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode *getChildGroupNode( const QString &id );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelNode *mParent = nullptr;
|
||||||
|
QList<QgsCoordinateReferenceSystemModelNode *> mChildren;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Coordinate reference system model node corresponding to a group
|
||||||
|
* \ingroup gui
|
||||||
|
* \warning Not available in Python bindings
|
||||||
|
* \since QGIS 3.34
|
||||||
|
*/
|
||||||
|
class GUI_EXPORT QgsCoordinateReferenceSystemModelGroupNode : public QgsCoordinateReferenceSystemModelNode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for QgsCoordinateReferenceSystemModelGroupNode.
|
||||||
|
*/
|
||||||
|
QgsCoordinateReferenceSystemModelGroupNode( const QString &name, const QIcon &icon, const QString &id );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the group's ID, which is non-translated.
|
||||||
|
*/
|
||||||
|
QString id() const { return mId; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the group's name, which is translated and user-visible.
|
||||||
|
*/
|
||||||
|
QString name() const { return mName; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the group's icon.
|
||||||
|
*/
|
||||||
|
QIcon icon() const { return mIcon; }
|
||||||
|
|
||||||
|
NodeType nodeType() const override { return NodeGroup; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QString mId;
|
||||||
|
QString mName;
|
||||||
|
QIcon mIcon;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Coordinate reference system model node corresponding to a CRS.
|
||||||
|
* \ingroup gui
|
||||||
|
* \warning Not available in Python bindings.
|
||||||
|
* \since QGIS 3.44
|
||||||
|
*/
|
||||||
|
class GUI_EXPORT QgsCoordinateReferenceSystemModelCrsNode : public QgsCoordinateReferenceSystemModelNode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor for QgsCoordinateReferenceSystemModelCrsNode, associated
|
||||||
|
* with the specified \a record.
|
||||||
|
*/
|
||||||
|
QgsCoordinateReferenceSystemModelCrsNode( const QgsCrsDbRecord &record );
|
||||||
|
|
||||||
|
NodeType nodeType() const override { return NodeCrs; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the record associated with this node.
|
||||||
|
*/
|
||||||
|
const QgsCrsDbRecord &record() const { return mRecord; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the \a wkt representation of the CRS.
|
||||||
|
*
|
||||||
|
* This is only used for non-standard CRS (i.e. those not present in the database).
|
||||||
|
*
|
||||||
|
* \see wkt()
|
||||||
|
*/
|
||||||
|
void setWkt( const QString &wkt ) { mWkt = wkt; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the WKT representation of the CRS.
|
||||||
|
*
|
||||||
|
* This is only used for non-standard CRS (i.e. those not present in the database).
|
||||||
|
*
|
||||||
|
* \see setWkt()
|
||||||
|
*/
|
||||||
|
QString wkt() const { return mWkt; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the \a proj representation of the CRS.
|
||||||
|
*
|
||||||
|
* This is only used for non-standard CRS (i.e. those not present in the database).
|
||||||
|
*
|
||||||
|
* \see proj()
|
||||||
|
*/
|
||||||
|
void setProj( const QString &proj ) { mProj = proj; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the PROJ representation of the CRS.
|
||||||
|
*
|
||||||
|
* This is only used for non-standard CRS (i.e. those not present in the database).
|
||||||
|
*
|
||||||
|
* \see setProj()
|
||||||
|
*/
|
||||||
|
QString proj() const { return mProj; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const QgsCrsDbRecord mRecord;
|
||||||
|
QString mWkt;
|
||||||
|
QString mProj;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
///@endcond
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class QgsCoordinateReferenceSystemModel
|
||||||
|
* \ingroup core
|
||||||
|
* \brief A tree model for display of known coordinate reference systems.
|
||||||
|
* \since QGIS 3.34
|
||||||
|
*/
|
||||||
|
class GUI_EXPORT QgsCoordinateReferenceSystemModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//! Custom roles used by the model
|
||||||
|
enum Roles
|
||||||
|
{
|
||||||
|
RoleNodeType = Qt::UserRole, //!< Corresponds to the node's type
|
||||||
|
RoleName = Qt::UserRole + 1, //!< The coordinate reference system name
|
||||||
|
RoleAuthId = Qt::UserRole + 2, //!< The coordinate reference system authority name and id
|
||||||
|
RoleDeprecated = Qt::UserRole + 3, //!< TRUE if the CRS is deprecated
|
||||||
|
RoleType = Qt::UserRole + 4, //!< The coordinate reference system type
|
||||||
|
RoleGroupId = Qt::UserRole + 5, //!< The node ID (for group nodes)
|
||||||
|
RoleWkt = Qt::UserRole + 6, //!< The coordinate reference system's WKT representation. This is only used for non-standard CRS (i.e. those not present in the database).
|
||||||
|
RoleProj = Qt::UserRole + 7, //!< The coordinate reference system's PROJ representation. This is only used for non-standard CRS (i.e. those not present in the database).
|
||||||
|
};
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModel( QObject *parent = nullptr );
|
||||||
|
|
||||||
|
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||||
|
QVariant data( const QModelIndex &index, int role ) const override;
|
||||||
|
QVariant headerData( int section, Qt::Orientation orientation, int role ) const override;
|
||||||
|
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
|
||||||
|
int columnCount( const QModelIndex & = QModelIndex() ) const override;
|
||||||
|
QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override;
|
||||||
|
QModelIndex parent( const QModelIndex &index ) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a custom \a crs to the model.
|
||||||
|
*
|
||||||
|
* This method can be used to add CRS which aren't present in either the standard PROJ SRS database or the
|
||||||
|
* user's custom CRS database to the model.
|
||||||
|
*/
|
||||||
|
void addCustomCrs( const QgsCoordinateReferenceSystem &crs );
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void rebuild();
|
||||||
|
void userCrsAdded( const QString &id );
|
||||||
|
void userCrsRemoved( long id );
|
||||||
|
void userCrsChanged( const QString &id );
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelCrsNode *addRecord( const QgsCrsDbRecord &record );
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModelNode *index2node( const QModelIndex &index ) const;
|
||||||
|
QModelIndex node2index( QgsCoordinateReferenceSystemModelNode *node ) const;
|
||||||
|
QModelIndex indexOfParentTreeNode( QgsCoordinateReferenceSystemModelNode *parentNode ) const;
|
||||||
|
|
||||||
|
|
||||||
|
std::unique_ptr< QgsCoordinateReferenceSystemModelGroupNode > mRootNode;
|
||||||
|
|
||||||
|
QList< QgsCrsDbRecord > mCrsDbRecords;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief A sort/filter proxy model for coordinate reference systems.
|
||||||
|
*
|
||||||
|
* \ingroup gui
|
||||||
|
* \since QGIS 3.34
|
||||||
|
*/
|
||||||
|
class GUI_EXPORT QgsCoordinateReferenceSystemProxyModel: 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 QgsCoordinateReferenceSystemProxyModel, with the given \a parent object.
|
||||||
|
*/
|
||||||
|
explicit QgsCoordinateReferenceSystemProxyModel( QObject *parent SIP_TRANSFERTHIS = nullptr );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the underlying source model.
|
||||||
|
*/
|
||||||
|
QgsCoordinateReferenceSystemModel *coordinateReferenceSystemModel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the underlying source model.
|
||||||
|
* \note Not available in Python bindings
|
||||||
|
*/
|
||||||
|
const QgsCoordinateReferenceSystemModel *coordinateReferenceSystemModel() const SIP_SKIP;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set \a filters that affect how CRS are filtered.
|
||||||
|
* \see filters()
|
||||||
|
*/
|
||||||
|
void setFilters( QgsCoordinateReferenceSystemProxyModel::Filters filters );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns any filters that affect how CRS are filtered.
|
||||||
|
* \see setFilters()
|
||||||
|
*/
|
||||||
|
Filters filters() const { return mFilters; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a \a filter string, such that only coordinate reference systems matching the
|
||||||
|
* specified string will be shown.
|
||||||
|
*
|
||||||
|
* \see filterString()
|
||||||
|
*/
|
||||||
|
void setFilterString( const QString &filter );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current filter string, if set.
|
||||||
|
*
|
||||||
|
* \see setFilterString()
|
||||||
|
*/
|
||||||
|
QString filterString() const { return mFilterString; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a \a filter list of CRS auth ID strings, such that only coordinate reference systems matching the
|
||||||
|
* specified auth IDs will be shown.
|
||||||
|
*
|
||||||
|
* \see filterAuthIds()
|
||||||
|
*/
|
||||||
|
void setFilterAuthIds( const QStringList &filter );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current filter list of auth ID strings, if set.
|
||||||
|
*
|
||||||
|
* \see setFilterString()
|
||||||
|
*/
|
||||||
|
QStringList filterAuthIds() const { return mFilterAuthIds; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether deprecated CRS should be filtered from the results.
|
||||||
|
*
|
||||||
|
* \see filterDeprecated()
|
||||||
|
*/
|
||||||
|
void setFilterDeprecated( bool filter );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether deprecated CRS will be filtered from the results.
|
||||||
|
*
|
||||||
|
* \see setFilterDeprecated()
|
||||||
|
*/
|
||||||
|
bool filterDeprecated() const { return mFilterDeprecated; }
|
||||||
|
|
||||||
|
bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const override;
|
||||||
|
bool lessThan( const QModelIndex &left, const QModelIndex &right ) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
QgsCoordinateReferenceSystemModel *mModel = nullptr;
|
||||||
|
QString mFilterString;
|
||||||
|
QStringList mFilterAuthIds;
|
||||||
|
bool mFilterDeprecated = false;
|
||||||
|
Filters mFilters = Filters();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // QGSCOORDINATEREFERENCESYSTEMMODEL_H
|
@ -63,6 +63,7 @@ ADD_PYTHON_TEST(PyQgsCoordinateFormatter test_qgscoordinateformatter.py)
|
|||||||
ADD_PYTHON_TEST(PyQgsCoordinateOperationWidget test_qgscoordinateoperationwidget.py)
|
ADD_PYTHON_TEST(PyQgsCoordinateOperationWidget test_qgscoordinateoperationwidget.py)
|
||||||
ADD_PYTHON_TEST(PyQgsConditionalFormatWidgets test_qgsconditionalformatwidgets.py)
|
ADD_PYTHON_TEST(PyQgsConditionalFormatWidgets test_qgsconditionalformatwidgets.py)
|
||||||
ADD_PYTHON_TEST(PyQgsCoordinateReferenceSystem test_qgscoordinatereferencesystem.py)
|
ADD_PYTHON_TEST(PyQgsCoordinateReferenceSystem test_qgscoordinatereferencesystem.py)
|
||||||
|
ADD_PYTHON_TEST(PyQgsCoordinateReferenceSystemModel test_qgscoordinatereferencesystemmodel.py)
|
||||||
ADD_PYTHON_TEST(PyQgsCoordinateReferenceSystemUtils test_qgscoordinatereferencesystemutils.py)
|
ADD_PYTHON_TEST(PyQgsCoordinateReferenceSystemUtils test_qgscoordinatereferencesystemutils.py)
|
||||||
ADD_PYTHON_TEST(PyQgsConditionalStyle test_qgsconditionalstyle.py)
|
ADD_PYTHON_TEST(PyQgsConditionalStyle test_qgsconditionalstyle.py)
|
||||||
ADD_PYTHON_TEST(PyQgsConnectionRegistry test_qgsconnectionregistry.py)
|
ADD_PYTHON_TEST(PyQgsConnectionRegistry test_qgsconnectionregistry.py)
|
||||||
|
548
tests/src/python/test_qgscoordinatereferencesystemmodel.py
Normal file
548
tests/src/python/test_qgscoordinatereferencesystemmodel.py
Normal file
@ -0,0 +1,548 @@
|
|||||||
|
"""QGIS Unit tests for QgsCoordinateReferenceSystemModel.
|
||||||
|
|
||||||
|
.. 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__ = '(C) 2022 by Nyall Dawson'
|
||||||
|
__date__ = '12/07/2023'
|
||||||
|
__copyright__ = 'Copyright 2023, The QGIS Project'
|
||||||
|
|
||||||
|
import qgis # NOQA
|
||||||
|
|
||||||
|
from qgis.PyQt.QtCore import (
|
||||||
|
Qt,
|
||||||
|
QModelIndex
|
||||||
|
)
|
||||||
|
from qgis.core import (
|
||||||
|
Qgis,
|
||||||
|
QgsApplication,
|
||||||
|
QgsCoordinateReferenceSystem,
|
||||||
|
QgsCoordinateReferenceSystemUtils,
|
||||||
|
)
|
||||||
|
from qgis.gui import (
|
||||||
|
QgsCoordinateReferenceSystemModel,
|
||||||
|
QgsCoordinateReferenceSystemProxyModel
|
||||||
|
)
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from qgis.testing import start_app, QgisTestCase
|
||||||
|
|
||||||
|
start_app()
|
||||||
|
|
||||||
|
|
||||||
|
class TestQgsCoordinateReferenceSystemModel(QgisTestCase):
|
||||||
|
|
||||||
|
def test_model(self):
|
||||||
|
model = QgsCoordinateReferenceSystemModel()
|
||||||
|
# top level items -- we expect to find Projected, Geographic (2D), Geographic (3D),
|
||||||
|
# Compound, Vertical amongst others
|
||||||
|
self.assertGreaterEqual(model.rowCount(QModelIndex()), 5)
|
||||||
|
top_level_items = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), Qt.DisplayRole) for row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertIn('Projected', top_level_items)
|
||||||
|
self.assertIn('Geographic (2D)', top_level_items)
|
||||||
|
self.assertIn('Geographic (3D)', top_level_items)
|
||||||
|
self.assertIn('Compound', top_level_items)
|
||||||
|
self.assertIn('Vertical', top_level_items)
|
||||||
|
|
||||||
|
# projection methods should not be at top level
|
||||||
|
self.assertNotIn('Cassini', top_level_items)
|
||||||
|
|
||||||
|
# user and custom groups should not be created until required
|
||||||
|
self.assertNotIn("User Defined Coordinate Systems", top_level_items)
|
||||||
|
self.assertNotIn("Custom Coordinate Systems", top_level_items)
|
||||||
|
|
||||||
|
# check group ids
|
||||||
|
top_level_item_group_ids = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), QgsCoordinateReferenceSystemModel.RoleGroupId) for row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertIn('Projected', top_level_item_group_ids)
|
||||||
|
self.assertIn('Geographic2d', top_level_item_group_ids)
|
||||||
|
self.assertIn('Geographic3d', top_level_item_group_ids)
|
||||||
|
self.assertIn('Compound', top_level_item_group_ids)
|
||||||
|
self.assertIn('Vertical', top_level_item_group_ids)
|
||||||
|
|
||||||
|
# find WGS84 in Geographic2d group
|
||||||
|
geographic_2d_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'Geographic2d'
|
||||||
|
][0]
|
||||||
|
|
||||||
|
# for proj 9, there's > 1300 crs in this group
|
||||||
|
self.assertGreaterEqual(model.rowCount(geographic_2d_index), 1000)
|
||||||
|
|
||||||
|
wgs84_index = [
|
||||||
|
model.index(row, 0, geographic_2d_index)
|
||||||
|
for row in range(model.rowCount(geographic_2d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_2d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4326'
|
||||||
|
][0]
|
||||||
|
# test model roles
|
||||||
|
self.assertEqual(model.data(wgs84_index, Qt.DisplayRole), 'WGS 84')
|
||||||
|
self.assertEqual(model.data(model.index(wgs84_index.row(), 1, wgs84_index.parent()), Qt.DisplayRole), 'EPSG:4326')
|
||||||
|
self.assertEqual(model.data(wgs84_index, QgsCoordinateReferenceSystemModel.RoleName), 'WGS 84')
|
||||||
|
self.assertFalse(model.data(wgs84_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleDeprecated))
|
||||||
|
# the proj and wkt roles are only available for non-standard CRS
|
||||||
|
self.assertFalse(model.data(wgs84_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleWkt))
|
||||||
|
self.assertFalse(model.data(wgs84_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleProj))
|
||||||
|
|
||||||
|
# check that same result is returned by authIdToIndex
|
||||||
|
self.assertEqual(model.authIdToIndex('EPSG:4326'), wgs84_index)
|
||||||
|
|
||||||
|
# find EPSG:4329 in Geographic3d group (also tests a deprecated CRS)
|
||||||
|
geographic_3d_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'Geographic3d'
|
||||||
|
][0]
|
||||||
|
|
||||||
|
# for proj 9, there's > 200 crs in this group
|
||||||
|
self.assertGreaterEqual(model.rowCount(geographic_3d_index), 200)
|
||||||
|
|
||||||
|
epsg_4329_index = [
|
||||||
|
model.index(row, 0, geographic_3d_index)
|
||||||
|
for row in range(model.rowCount(geographic_3d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_3d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4329'
|
||||||
|
][0]
|
||||||
|
# test model roles
|
||||||
|
self.assertEqual(model.data(epsg_4329_index, Qt.DisplayRole), 'WGS 84 (3D)')
|
||||||
|
self.assertEqual(
|
||||||
|
model.data(model.index(epsg_4329_index.row(), 1, epsg_4329_index.parent()),
|
||||||
|
Qt.DisplayRole), 'EPSG:4329')
|
||||||
|
self.assertEqual(model.data(epsg_4329_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleName),
|
||||||
|
'WGS 84 (3D)')
|
||||||
|
self.assertTrue(model.data(epsg_4329_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleDeprecated))
|
||||||
|
# the proj and wkt roles are only available for non-standard CRS
|
||||||
|
self.assertFalse(model.data(epsg_4329_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleWkt))
|
||||||
|
self.assertFalse(model.data(epsg_4329_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleProj))
|
||||||
|
|
||||||
|
# check that same result is returned by authIdToIndex
|
||||||
|
self.assertEqual(model.authIdToIndex('EPSG:4329'), epsg_4329_index)
|
||||||
|
|
||||||
|
# find a vertical crs
|
||||||
|
vertical_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'Vertical'
|
||||||
|
][0]
|
||||||
|
|
||||||
|
# for proj 9, there's > 400 crs in this group
|
||||||
|
self.assertGreaterEqual(model.rowCount(vertical_index), 400)
|
||||||
|
|
||||||
|
ahd_index = [
|
||||||
|
model.index(row, 0, vertical_index)
|
||||||
|
for row in range(model.rowCount(vertical_index))
|
||||||
|
if model.data(model.index(row, 0, vertical_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:5711'
|
||||||
|
][0]
|
||||||
|
# test model roles
|
||||||
|
self.assertEqual(model.data(ahd_index, Qt.DisplayRole), 'AHD height')
|
||||||
|
self.assertEqual(
|
||||||
|
model.data(model.index(ahd_index.row(), 1, ahd_index.parent()),
|
||||||
|
Qt.DisplayRole), 'EPSG:5711')
|
||||||
|
self.assertEqual(model.data(ahd_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleName),
|
||||||
|
'AHD height')
|
||||||
|
self.assertFalse(model.data(ahd_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleDeprecated))
|
||||||
|
# the proj and wkt roles are only available for non-standard CRS
|
||||||
|
self.assertFalse(model.data(ahd_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleWkt))
|
||||||
|
self.assertFalse(model.data(ahd_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleProj))
|
||||||
|
|
||||||
|
# check that same result is returned by authIdToIndex
|
||||||
|
self.assertEqual(model.authIdToIndex('EPSG:5711'), ahd_index)
|
||||||
|
|
||||||
|
# check projected group
|
||||||
|
projected_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'Projected'
|
||||||
|
][0]
|
||||||
|
# for proj 9, there's > 50 projection methods in this group
|
||||||
|
self.assertGreaterEqual(model.rowCount(projected_index), 50)
|
||||||
|
|
||||||
|
# find Albers equal area group
|
||||||
|
aea_group_index = [
|
||||||
|
model.index(row, 0, projected_index)
|
||||||
|
for row in range(model.rowCount(projected_index))
|
||||||
|
if model.data(model.index(row, 0, projected_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'aea'
|
||||||
|
][0]
|
||||||
|
# for proj 9, there's > 100 crs in this group
|
||||||
|
self.assertGreaterEqual(model.rowCount(aea_group_index), 100)
|
||||||
|
|
||||||
|
# find epsg:3577 in this group
|
||||||
|
epsg_3577_index = [
|
||||||
|
model.index(row, 0, aea_group_index)
|
||||||
|
for row in range(model.rowCount(aea_group_index))
|
||||||
|
if model.data(model.index(row, 0, aea_group_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:3577'
|
||||||
|
][0]
|
||||||
|
# test model roles
|
||||||
|
self.assertEqual(model.data(epsg_3577_index, Qt.DisplayRole), 'GDA94 / Australian Albers')
|
||||||
|
self.assertEqual(
|
||||||
|
model.data(model.index(epsg_3577_index.row(), 1, epsg_3577_index.parent()),
|
||||||
|
Qt.DisplayRole), 'EPSG:3577')
|
||||||
|
self.assertEqual(model.data(epsg_3577_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleName),
|
||||||
|
'GDA94 / Australian Albers')
|
||||||
|
self.assertFalse(model.data(epsg_3577_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleDeprecated))
|
||||||
|
# the proj and wkt roles are only available for non-standard CRS
|
||||||
|
self.assertFalse(model.data(epsg_3577_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleWkt))
|
||||||
|
self.assertFalse(model.data(epsg_3577_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleProj))
|
||||||
|
|
||||||
|
# check that same result is returned by authIdToIndex
|
||||||
|
self.assertEqual(model.authIdToIndex('EPSG:3577'), epsg_3577_index)
|
||||||
|
|
||||||
|
# now add a custom crs and ensure it appears in the model
|
||||||
|
prev_top_level_count = model.rowCount(QModelIndex())
|
||||||
|
registry = QgsApplication.coordinateReferenceSystemRegistry()
|
||||||
|
crs = QgsCoordinateReferenceSystem.fromProj("+proj=aea +lat_1=20 +lat_2=-23 +lat_0=4 +lon_0=29 +x_0=10 +y_0=3 +datum=WGS84 +units=m +no_defs")
|
||||||
|
res = registry.addUserCrs(crs, 'my custom crs')
|
||||||
|
self.assertEqual(res, 100000)
|
||||||
|
|
||||||
|
self.assertEqual(model.rowCount(QModelIndex()), prev_top_level_count + 1)
|
||||||
|
top_level_items = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), Qt.DisplayRole) for row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertIn('User Defined Coordinate Systems', top_level_items)
|
||||||
|
self.assertNotIn("Custom Coordinate Systems", top_level_items)
|
||||||
|
|
||||||
|
# check group ids
|
||||||
|
top_level_item_group_ids = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), QgsCoordinateReferenceSystemModel.RoleGroupId) for row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertIn('USER', top_level_item_group_ids)
|
||||||
|
|
||||||
|
# find user crs
|
||||||
|
user_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'USER'
|
||||||
|
][0]
|
||||||
|
self.assertEqual(model.rowCount(user_index), 1)
|
||||||
|
|
||||||
|
user_crs_index = model.index(0, 0, user_index)
|
||||||
|
# test model roles
|
||||||
|
self.assertEqual(model.data(user_crs_index, Qt.DisplayRole), 'my custom crs')
|
||||||
|
self.assertEqual(
|
||||||
|
model.data(model.index(user_crs_index.row(), 1, user_crs_index.parent()),
|
||||||
|
Qt.DisplayRole), 'USER:100000')
|
||||||
|
self.assertEqual(model.data(user_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleName),
|
||||||
|
'my custom crs')
|
||||||
|
self.assertFalse(model.data(user_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleDeprecated))
|
||||||
|
# the proj and wkt roles are only available for non-standard CRS
|
||||||
|
self.assertEqual(model.data(user_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleWkt)[:8], 'PROJCRS[')
|
||||||
|
self.assertEqual(model.data(user_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleProj), "+proj=aea +lat_1=20 +lat_2=-23 +lat_0=4 +lon_0=29 +x_0=10 +y_0=3 +datum=WGS84 +units=m +no_defs")
|
||||||
|
|
||||||
|
# check that same result is returned by authIdToIndex
|
||||||
|
self.assertEqual(model.authIdToIndex('USER:100000'), user_crs_index)
|
||||||
|
|
||||||
|
# modify user crs
|
||||||
|
crs = QgsCoordinateReferenceSystem.fromProj("+proj=aea +lat_1=21 +lat_2=-23 +lat_0=4 +lon_0=29 +x_0=10 +y_0=3 +datum=WGS84 +units=m +no_defs")
|
||||||
|
self.assertTrue(registry.updateUserCrs(100000, crs, 'my custom crs rev 2'))
|
||||||
|
user_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'USER'
|
||||||
|
][0]
|
||||||
|
self.assertEqual(model.rowCount(user_index), 1)
|
||||||
|
|
||||||
|
user_crs_index = model.index(0, 0, user_index)
|
||||||
|
# test model roles
|
||||||
|
self.assertEqual(model.data(user_crs_index, Qt.DisplayRole), 'my custom crs rev 2')
|
||||||
|
self.assertEqual(
|
||||||
|
model.data(model.index(user_crs_index.row(), 1, user_crs_index.parent()),
|
||||||
|
Qt.DisplayRole), 'USER:100000')
|
||||||
|
self.assertEqual(model.data(user_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleName),
|
||||||
|
'my custom crs rev 2')
|
||||||
|
self.assertFalse(model.data(user_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleDeprecated))
|
||||||
|
# the proj and wkt roles are only available for non-standard CRS
|
||||||
|
self.assertEqual(model.data(user_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleWkt)[:8], 'PROJCRS[')
|
||||||
|
self.assertEqual(model.data(user_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleProj), "+proj=aea +lat_1=21 +lat_2=-23 +lat_0=4 +lon_0=29 +x_0=10 +y_0=3 +datum=WGS84 +units=m +no_defs")
|
||||||
|
|
||||||
|
# remove
|
||||||
|
registry.removeUserCrs(100000)
|
||||||
|
self.assertEqual(model.rowCount(user_index), 0)
|
||||||
|
|
||||||
|
# add a non-standard crs (does not correspond to any db entry)
|
||||||
|
prev_top_level_count = model.rowCount(QModelIndex())
|
||||||
|
crs = QgsCoordinateReferenceSystem.fromProj(
|
||||||
|
"+proj=aea +lat_1=1.5 +lat_2=-23 +lat_0=4 +lon_0=29 +x_0=10 +y_0=3 +datum=WGS84 +units=m +no_defs")
|
||||||
|
model.addCustomCrs(crs)
|
||||||
|
|
||||||
|
self.assertEqual(model.rowCount(QModelIndex()), prev_top_level_count + 1)
|
||||||
|
top_level_items = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), Qt.DisplayRole) for row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertIn("Custom Coordinate Systems", top_level_items)
|
||||||
|
|
||||||
|
# check group ids
|
||||||
|
top_level_item_group_ids = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), QgsCoordinateReferenceSystemModel.RoleGroupId) for row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertIn('CUSTOM', top_level_item_group_ids)
|
||||||
|
custom_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'CUSTOM'
|
||||||
|
][0]
|
||||||
|
self.assertEqual(model.rowCount(custom_index), 1)
|
||||||
|
|
||||||
|
custom_crs_index = model.index(0, 0, custom_index)
|
||||||
|
# test model roles
|
||||||
|
self.assertEqual(model.data(custom_crs_index, Qt.DisplayRole), 'Custom CRS')
|
||||||
|
self.assertFalse(
|
||||||
|
model.data(model.index(custom_crs_index.row(), 1, custom_crs_index.parent()),
|
||||||
|
Qt.DisplayRole))
|
||||||
|
self.assertEqual(model.data(custom_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleName), 'Custom CRS')
|
||||||
|
self.assertFalse(model.data(custom_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleDeprecated))
|
||||||
|
# the proj and wkt roles are only available for non-standard CRS
|
||||||
|
self.assertEqual(model.data(custom_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleWkt)[:8], 'PROJCRS[')
|
||||||
|
self.assertEqual(model.data(custom_crs_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleProj), "+proj=aea +lat_1=1.5 +lat_2=-23 +lat_0=4 +lon_0=29 +x_0=10 +y_0=3 +datum=WGS84 +units=m +no_defs")
|
||||||
|
|
||||||
|
def test_proxy_model(self):
|
||||||
|
model = QgsCoordinateReferenceSystemProxyModel()
|
||||||
|
# top level items -- we expect to find Projected, Geographic (2D), Geographic (3D),
|
||||||
|
# Compound, Vertical amongst others
|
||||||
|
self.assertGreaterEqual(model.rowCount(QModelIndex()), 5)
|
||||||
|
top_level_items = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), Qt.DisplayRole) for row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertIn('Projected', top_level_items)
|
||||||
|
self.assertIn('Geographic (2D)', top_level_items)
|
||||||
|
self.assertIn('Geographic (3D)', top_level_items)
|
||||||
|
self.assertIn('Compound', top_level_items)
|
||||||
|
self.assertIn('Vertical', top_level_items)
|
||||||
|
|
||||||
|
# filter by type
|
||||||
|
model.setFilters(QgsCoordinateReferenceSystemProxyModel.FilterHorizontal)
|
||||||
|
top_level_items = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), Qt.DisplayRole) for
|
||||||
|
row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertIn('Projected', top_level_items)
|
||||||
|
self.assertIn('Geographic (2D)', top_level_items)
|
||||||
|
self.assertIn('Geographic (3D)', top_level_items)
|
||||||
|
self.assertNotIn('Compound', top_level_items)
|
||||||
|
self.assertNotIn('Vertical', top_level_items)
|
||||||
|
|
||||||
|
model.setFilters(QgsCoordinateReferenceSystemProxyModel.FilterVertical)
|
||||||
|
top_level_items = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), Qt.DisplayRole) for
|
||||||
|
row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertNotIn('Projected', top_level_items)
|
||||||
|
self.assertNotIn('Geographic (2D)', top_level_items)
|
||||||
|
self.assertNotIn('Geographic (3D)', top_level_items)
|
||||||
|
self.assertNotIn('Compound', top_level_items)
|
||||||
|
self.assertIn('Vertical', top_level_items)
|
||||||
|
|
||||||
|
model.setFilters(QgsCoordinateReferenceSystemProxyModel.FilterCompound)
|
||||||
|
top_level_items = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), Qt.DisplayRole) for
|
||||||
|
row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertNotIn('Projected', top_level_items)
|
||||||
|
self.assertNotIn('Geographic (2D)', top_level_items)
|
||||||
|
self.assertNotIn('Geographic (3D)', top_level_items)
|
||||||
|
self.assertIn('Compound', top_level_items)
|
||||||
|
self.assertNotIn('Vertical', top_level_items)
|
||||||
|
|
||||||
|
model.setFilters(QgsCoordinateReferenceSystemProxyModel.Filters(QgsCoordinateReferenceSystemProxyModel.FilterCompound
|
||||||
|
| QgsCoordinateReferenceSystemProxyModel.FilterVertical))
|
||||||
|
top_level_items = [
|
||||||
|
model.data(model.index(row, 0, QModelIndex()), Qt.DisplayRole) for
|
||||||
|
row in range(model.rowCount(QModelIndex()))
|
||||||
|
]
|
||||||
|
self.assertNotIn('Projected', top_level_items)
|
||||||
|
self.assertNotIn('Geographic (2D)', top_level_items)
|
||||||
|
self.assertNotIn('Geographic (3D)', top_level_items)
|
||||||
|
self.assertIn('Compound', top_level_items)
|
||||||
|
self.assertIn('Vertical', top_level_items)
|
||||||
|
|
||||||
|
model.setFilters(QgsCoordinateReferenceSystemProxyModel.Filters())
|
||||||
|
|
||||||
|
# find WGS84 in Geographic2d group
|
||||||
|
geographic_2d_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'Geographic2d'
|
||||||
|
][0]
|
||||||
|
|
||||||
|
wgs84_index = [
|
||||||
|
model.index(row, 0, geographic_2d_index)
|
||||||
|
for row in range(model.rowCount(geographic_2d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_2d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4326'
|
||||||
|
][0]
|
||||||
|
# test model roles
|
||||||
|
self.assertEqual(model.data(wgs84_index, Qt.DisplayRole), 'WGS 84')
|
||||||
|
self.assertEqual(model.data(model.index(wgs84_index.row(), 1, wgs84_index.parent()), Qt.DisplayRole), 'EPSG:4326')
|
||||||
|
self.assertEqual(model.data(wgs84_index, QgsCoordinateReferenceSystemModel.RoleName), 'WGS 84')
|
||||||
|
self.assertFalse(model.data(wgs84_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleDeprecated))
|
||||||
|
# the proj and wkt roles are only available for non-standard CRS
|
||||||
|
self.assertFalse(model.data(wgs84_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleWkt))
|
||||||
|
self.assertFalse(model.data(wgs84_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleProj))
|
||||||
|
|
||||||
|
# find EPSG:4329 in Geographic3d group (also tests a deprecated CRS)
|
||||||
|
geographic_3d_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'Geographic3d'
|
||||||
|
][0]
|
||||||
|
|
||||||
|
epsg_4329_index = [
|
||||||
|
model.index(row, 0, geographic_3d_index)
|
||||||
|
for row in range(model.rowCount(geographic_3d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_3d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4329'
|
||||||
|
][0]
|
||||||
|
# test model roles
|
||||||
|
self.assertEqual(model.data(epsg_4329_index, Qt.DisplayRole), 'WGS 84 (3D)')
|
||||||
|
self.assertEqual(
|
||||||
|
model.data(model.index(epsg_4329_index.row(), 1, epsg_4329_index.parent()),
|
||||||
|
Qt.DisplayRole), 'EPSG:4329')
|
||||||
|
self.assertEqual(model.data(epsg_4329_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleName),
|
||||||
|
'WGS 84 (3D)')
|
||||||
|
self.assertTrue(model.data(epsg_4329_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleDeprecated))
|
||||||
|
# the proj and wkt roles are only available for non-standard CRS
|
||||||
|
self.assertFalse(model.data(epsg_4329_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleWkt))
|
||||||
|
self.assertFalse(model.data(epsg_4329_index,
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleProj))
|
||||||
|
|
||||||
|
model.setFilterDeprecated(True)
|
||||||
|
geographic_3d_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'Geographic3d'
|
||||||
|
][0]
|
||||||
|
self.assertFalse([
|
||||||
|
model.index(row, 0, geographic_3d_index)
|
||||||
|
for row in range(model.rowCount(geographic_3d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_3d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4329'
|
||||||
|
])
|
||||||
|
model.setFilterDeprecated(False)
|
||||||
|
geographic_3d_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'Geographic3d'
|
||||||
|
][0]
|
||||||
|
epsg_4329_index = [
|
||||||
|
model.index(row, 0, geographic_3d_index)
|
||||||
|
for row in range(model.rowCount(geographic_3d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_3d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4329'
|
||||||
|
][0]
|
||||||
|
self.assertTrue(epsg_4329_index.isValid())
|
||||||
|
|
||||||
|
# filter by string
|
||||||
|
model.setFilterString('GDA94')
|
||||||
|
geographic_3d_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'Geographic3d'
|
||||||
|
][0]
|
||||||
|
self.assertFalse([
|
||||||
|
model.index(row, 0, geographic_3d_index)
|
||||||
|
for row in range(model.rowCount(geographic_3d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_3d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4329'
|
||||||
|
])
|
||||||
|
epsg_4939_index = [
|
||||||
|
model.index(row, 0, geographic_3d_index)
|
||||||
|
for row in range(model.rowCount(geographic_3d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_3d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4939'
|
||||||
|
][0]
|
||||||
|
self.assertTrue(epsg_4939_index.isValid())
|
||||||
|
epsg_4347_index = [
|
||||||
|
model.index(row, 0, geographic_3d_index)
|
||||||
|
for row in range(model.rowCount(geographic_3d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_3d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4347'
|
||||||
|
][0]
|
||||||
|
self.assertTrue(epsg_4347_index.isValid())
|
||||||
|
|
||||||
|
model.setFilterString('')
|
||||||
|
|
||||||
|
# set filtered list of crs to show
|
||||||
|
model.setFilterAuthIds({'epsg:4289', 'EPSG:4196'})
|
||||||
|
geographic_2d_index = [
|
||||||
|
model.index(row, 0, QModelIndex())
|
||||||
|
for row in range(model.rowCount(QModelIndex()))
|
||||||
|
if model.data(model.index(row, 0, QModelIndex()),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleGroupId) == 'Geographic2d'
|
||||||
|
][0]
|
||||||
|
self.assertFalse([
|
||||||
|
model.index(row, 0, geographic_2d_index)
|
||||||
|
for row in range(model.rowCount(geographic_2d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_2d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4169'
|
||||||
|
])
|
||||||
|
epsg_4289_index = [
|
||||||
|
model.index(row, 0, geographic_2d_index)
|
||||||
|
for row in range(model.rowCount(geographic_2d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_2d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4289'
|
||||||
|
][0]
|
||||||
|
self.assertTrue(epsg_4289_index.isValid())
|
||||||
|
epsg_4196_index = [
|
||||||
|
model.index(row, 0, geographic_2d_index)
|
||||||
|
for row in range(model.rowCount(geographic_2d_index))
|
||||||
|
if model.data(model.index(row, 0, geographic_2d_index),
|
||||||
|
QgsCoordinateReferenceSystemModel.RoleAuthId) == 'EPSG:4196'
|
||||||
|
][0]
|
||||||
|
self.assertTrue(epsg_4196_index.isValid())
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user