18#include "moc_qgscoordinatereferencesystemmodel.cpp" 
   26  : QAbstractItemModel( parent )
 
   27  , mRootNode( std::make_unique<QgsCoordinateReferenceSystemModelGroupNode>( QString(), QIcon(), QString() ) )
 
 
   40  if ( !
index.isValid() )
 
   42    return Qt::ItemFlags();
 
   45  QgsCoordinateReferenceSystemModelNode *n = index2node( 
index );
 
   47    return Qt::ItemFlags();
 
   49  switch ( n->nodeType() )
 
   51    case QgsCoordinateReferenceSystemModelNode::NodeGroup:
 
   52      return index.column() == 0 ? Qt::ItemIsEnabled : Qt::ItemFlags();
 
   53    case QgsCoordinateReferenceSystemModelNode::NodeCrs:
 
   54      return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
 
 
   61  if ( !
index.isValid() )
 
   64  QgsCoordinateReferenceSystemModelNode *n = index2node( 
index );
 
   71  switch ( n->nodeType() )
 
   73    case QgsCoordinateReferenceSystemModelNode::NodeGroup:
 
   75      QgsCoordinateReferenceSystemModelGroupNode *groupNode = qgis::down_cast<QgsCoordinateReferenceSystemModelGroupNode *>( n );
 
   78        case Qt::DecorationRole:
 
   79          switch ( 
index.column() )
 
   82              return groupNode->icon();
 
   90          switch ( 
index.column() )
 
   93              return groupNode->name();
 
  103          font.setItalic( 
true );
 
  104          if ( groupNode->parent() == mRootNode.get() )
 
  106            font.setBold( 
true );
 
  112          return groupNode->id();
 
  116    case QgsCoordinateReferenceSystemModelNode::NodeCrs:
 
  118      QgsCoordinateReferenceSystemModelCrsNode *crsNode = qgis::down_cast<QgsCoordinateReferenceSystemModelCrsNode *>( n );
 
  121        case Qt::DisplayRole:
 
  122        case Qt::ToolTipRole:
 
  123          switch ( 
index.column() )
 
  126              return crsNode->record().description;
 
  130              if ( crsNode->record().authName == QLatin1String( 
"CUSTOM" ) )
 
  132              return QStringLiteral( 
"%1:%2" ).arg( crsNode->record().authName, crsNode->record().authId );
 
  141          return crsNode->record().description;
 
  144          if ( !crsNode->record().authId.isEmpty() )
 
  145            return QStringLiteral( 
"%1:%2" ).arg( crsNode->record().authName, crsNode->record().authId );
 
  150          return crsNode->record().deprecated;
 
  153          return QVariant::fromValue( crsNode->record().type );
 
  156          return crsNode->wkt();
 
  159          return crsNode->proj();
 
  162          return crsNode->group();
 
  165          return crsNode->projection();
 
 
  177  if ( orientation == Qt::Horizontal )
 
  181      case Qt::DisplayRole:
 
  185            return tr( 
"Coordinate Reference System" );
 
  187            return tr( 
"Authority ID" );
 
 
  202  QgsCoordinateReferenceSystemModelNode *n = index2node( 
parent );
 
  206  return n->children().count();
 
 
  216  if ( !hasIndex( row, column, 
parent ) )
 
  217    return QModelIndex();
 
  219  QgsCoordinateReferenceSystemModelNode *n = index2node( 
parent );
 
  221    return QModelIndex(); 
 
  223  return createIndex( row, column, n->children().at( row ) );
 
 
  228  if ( !child.isValid() )
 
  229    return QModelIndex();
 
  231  if ( QgsCoordinateReferenceSystemModelNode *n = index2node( child ) )
 
  233    return indexOfParentTreeNode( n->parent() ); 
 
  238    return QModelIndex();
 
 
  244  const QModelIndex startIndex = 
index( 0, 0 );
 
  245  const QModelIndexList hits = match( startIndex, 
static_cast<int>( 
CustomRole::AuthId ), authid, 1, Qt::MatchRecursive );
 
  246  return hits.value( 0 );
 
 
  249void QgsCoordinateReferenceSystemModel::rebuild()
 
  253  mRootNode->deleteChildren();
 
  255  for ( 
const QgsCrsDbRecord &record : std::as_const( mCrsDbRecords ) )
 
  264    userRecord.
authName = QStringLiteral( 
"USER" );
 
  265    userRecord.
authId = QString::number( details.id );
 
  268    addRecord( userRecord );
 
  274void QgsCoordinateReferenceSystemModel::userCrsAdded( 
const QString &
id )
 
  279    if ( QStringLiteral( 
"USER:%1" ).arg( details.id ) == 
id )
 
  282      userRecord.
authName = QStringLiteral( 
"USER" );
 
  283      userRecord.
authId = QString::number( details.id );
 
  286      QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( 
"USER" ) );
 
  289        auto newGroup = std::make_unique<QgsCoordinateReferenceSystemModelGroupNode>(
 
  290          tr( 
"User-defined" ),
 
  293        beginInsertRows( QModelIndex(), mRootNode->children().length(), mRootNode->children().length() );
 
  294        mRootNode->addChildNode( newGroup.get() );
 
  296        group = newGroup.release();
 
  299      const QModelIndex parentGroupIndex = node2index( group );
 
  301      beginInsertRows( parentGroupIndex, group->children().size(), group->children().size() );
 
  302      QgsCoordinateReferenceSystemModelCrsNode *crsNode = addRecord( userRecord );
 
  303      crsNode->setProj( details.proj );
 
  304      crsNode->setWkt( details.wkt );
 
  311void QgsCoordinateReferenceSystemModel::userCrsRemoved( 
long id )
 
  313  QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( 
"USER" ) );
 
  316    for ( 
int row = 0; row < group->children().size(); ++row )
 
  318      if ( QgsCoordinateReferenceSystemModelCrsNode *crsNode = 
dynamic_cast<QgsCoordinateReferenceSystemModelCrsNode *
>( group->children().at( row ) ) )
 
  320        if ( crsNode->record().authId == QString::number( 
id ) )
 
  322          const QModelIndex parentIndex = node2index( group );
 
  323          beginRemoveRows( parentIndex, row, row );
 
  324          delete group->takeChild( crsNode );
 
  333void QgsCoordinateReferenceSystemModel::userCrsChanged( 
const QString &
id )
 
  335  QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( 
"USER" ) );
 
  338    for ( 
int row = 0; row < group->children().size(); ++row )
 
  340      if ( QgsCoordinateReferenceSystemModelCrsNode *crsNode = 
dynamic_cast<QgsCoordinateReferenceSystemModelCrsNode *
>( group->children().at( row ) ) )
 
  342        if ( QStringLiteral( 
"USER:%1" ).arg( crsNode->record().authId ) == 
id )
 
  345          const QModelIndex parentIndex = node2index( group );
 
  346          beginRemoveRows( parentIndex, row, row );
 
  347          delete group->takeChild( crsNode );
 
  358QgsCoordinateReferenceSystemModelCrsNode *QgsCoordinateReferenceSystemModel::addRecord( 
const QgsCrsDbRecord &record )
 
  360  QgsCoordinateReferenceSystemModelGroupNode *parentNode = mRootNode.get();
 
  361  auto crsNode = std::make_unique<QgsCoordinateReferenceSystemModelCrsNode>( record );
 
  366  if ( record.
authName == QLatin1String( 
"USER" ) )
 
  368    groupName = tr( 
"User-defined" );
 
  369    groupId = QStringLiteral( 
"USER" );
 
  372  else if ( record.
authName == QLatin1String( 
"CUSTOM" ) )
 
  375    groupId = QStringLiteral( 
"CUSTOM" );
 
  380    switch ( record.
type )
 
  385        groupName = tr( 
"Geodetic" );
 
  389        groupName = tr( 
"Geocentric" );
 
  393        groupName = tr( 
"Geographic (2D)" );
 
  398        groupName = tr( 
"Geographic (3D)" );
 
  403        groupName = tr( 
"Vertical" );
 
  408        groupName = tr( 
"Projected" );
 
  413        groupName = tr( 
"Compound" );
 
  417        groupName = tr( 
"Temporal" );
 
  421        groupName = tr( 
"Engineering" );
 
  425        groupName = tr( 
"Bound" );
 
  429        groupName = tr( 
"Other" );
 
  433  crsNode->setGroup( groupName );
 
  435  if ( QgsCoordinateReferenceSystemModelGroupNode *group = parentNode->getChildGroupNode( groupId ) )
 
  441    auto newGroup = std::make_unique<QgsCoordinateReferenceSystemModelGroupNode>( groupName, groupIcon, groupId );
 
  442    parentNode->addChildNode( newGroup.get() );
 
  443    parentNode = newGroup.release();
 
  449    if ( projectionName.isEmpty() )
 
  450      projectionName = tr( 
"Other" );
 
  452      crsNode->setProjection( projectionName );
 
  454    if ( QgsCoordinateReferenceSystemModelGroupNode *group = parentNode->getChildGroupNode( record.
projectionAcronym ) )
 
  460      auto newGroup = std::make_unique<QgsCoordinateReferenceSystemModelGroupNode>( projectionName, QIcon(), record.
projectionAcronym );
 
  461      parentNode->addChildNode( newGroup.get() );
 
  462      parentNode = newGroup.release();
 
  466  parentNode->addChildNode( crsNode.get() );
 
  467  return crsNode.release();
 
  473  userRecord.
authName = QStringLiteral( 
"CUSTOM" );
 
  477  QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( 
"CUSTOM" ) );
 
  480    auto newGroup = std::make_unique<QgsCoordinateReferenceSystemModelGroupNode>(
 
  484    beginInsertRows( QModelIndex(), mRootNode->children().length(), mRootNode->children().length() );
 
  485    mRootNode->addChildNode( newGroup.get() );
 
  487    group = newGroup.release();
 
  490  const QModelIndex parentGroupIndex = node2index( group );
 
  492  const int newRow = group->children().size();
 
  493  beginInsertRows( parentGroupIndex, newRow, newRow );
 
  494  QgsCoordinateReferenceSystemModelCrsNode *node = addRecord( userRecord );
 
  499  return index( newRow, 0, parentGroupIndex );
 
 
  502QgsCoordinateReferenceSystemModelNode *QgsCoordinateReferenceSystemModel::index2node( 
const QModelIndex &index )
 const 
  504  if ( !
index.isValid() )
 
  505    return mRootNode.get();
 
  507  return reinterpret_cast<QgsCoordinateReferenceSystemModelNode *
>( 
index.internalPointer() );
 
  510QModelIndex QgsCoordinateReferenceSystemModel::node2index( QgsCoordinateReferenceSystemModelNode *node )
 const 
  512  if ( !node || !node->parent() )
 
  513    return QModelIndex(); 
 
  515  QModelIndex parentIndex = node2index( node->parent() );
 
  517  int row = node->parent()->children().indexOf( node );
 
  518  Q_ASSERT( row >= 0 );
 
  519  return index( row, 0, parentIndex );
 
  522QModelIndex QgsCoordinateReferenceSystemModel::indexOfParentTreeNode( QgsCoordinateReferenceSystemModelNode *parentNode )
 const 
  524  Q_ASSERT( parentNode );
 
  526  QgsCoordinateReferenceSystemModelNode *grandParentNode = parentNode->parent();
 
  527  if ( !grandParentNode )
 
  528    return QModelIndex(); 
 
  530  int row = grandParentNode->children().indexOf( parentNode );
 
  531  Q_ASSERT( row >= 0 );
 
  533  return createIndex( row, 0, parentNode );
 
  537QgsCoordinateReferenceSystemModelNode::~QgsCoordinateReferenceSystemModelNode()
 
  539  qDeleteAll( mChildren );
 
  542QgsCoordinateReferenceSystemModelNode *QgsCoordinateReferenceSystemModelNode::takeChild( QgsCoordinateReferenceSystemModelNode *node )
 
  544  return mChildren.takeAt( mChildren.indexOf( node ) );
 
  547void QgsCoordinateReferenceSystemModelNode::addChildNode( QgsCoordinateReferenceSystemModelNode *node )
 
  552  Q_ASSERT( !node->mParent );
 
  553  node->mParent = 
this;
 
  555  mChildren.append( node );
 
  558void QgsCoordinateReferenceSystemModelNode::deleteChildren()
 
  560  qDeleteAll( mChildren );
 
  564QgsCoordinateReferenceSystemModelGroupNode *QgsCoordinateReferenceSystemModelNode::getChildGroupNode( 
const QString &
id )
 
  566  for ( QgsCoordinateReferenceSystemModelNode *node : std::as_const( mChildren ) )
 
  568    if ( node->nodeType() == NodeGroup )
 
  570      QgsCoordinateReferenceSystemModelGroupNode *groupNode = qgis::down_cast<QgsCoordinateReferenceSystemModelGroupNode *>( node );
 
  571      if ( groupNode && groupNode->id() == 
id )
 
  578QgsCoordinateReferenceSystemModelGroupNode::QgsCoordinateReferenceSystemModelGroupNode( 
const QString &name, 
const QIcon &icon, 
const QString &
id )
 
  585QgsCoordinateReferenceSystemModelCrsNode::QgsCoordinateReferenceSystemModelCrsNode( 
const QgsCrsDbRecord &record )
 
  597  : QSortFilterProxyModel( parent )
 
  600  setSourceModel( mModel );
 
  601  setDynamicSortFilter( 
true );
 
  602  setSortLocaleAware( 
true );
 
  603  setFilterCaseSensitivity( Qt::CaseInsensitive );
 
  604  setRecursiveFilteringEnabled( 
true );
 
 
  629  mFilterString = filter;
 
 
  635  if ( mFilterAuthIds == filter )
 
  638  mFilterAuthIds.clear();
 
  639  mFilterAuthIds.reserve( filter.size() );
 
  640  for ( 
const QString &
id : filter )
 
  642    mFilterAuthIds.insert( 
id.toUpper() );
 
 
  649  if ( mFilterDeprecated == filter )
 
  652  mFilterDeprecated = filter;
 
 
  658  if ( mFilterString.trimmed().isEmpty() && !mFilters && !mFilterDeprecated && mFilterAuthIds.isEmpty() )
 
  661  const QModelIndex sourceIndex = mModel->
index( sourceRow, 0, sourceParent );
 
  665    case QgsCoordinateReferenceSystemModelNode::NodeGroup:
 
  667    case QgsCoordinateReferenceSystemModelNode::NodeCrs:
 
  672  if ( mFilterDeprecated && deprecated )
 
  710  if ( !mFilterAuthIds.isEmpty() )
 
  712    if ( !mFilterAuthIds.contains( authid.toUpper() ) )
 
  716  if ( !mFilterString.trimmed().isEmpty() )
 
  719    QString candidate = name;
 
  721    if ( !groupName.isEmpty() )
 
  722      candidate += 
' ' + groupName;
 
  724    if ( !projectionName.isEmpty() )
 
  725      candidate += 
' ' + projectionName;
 
  728            || authid.contains( mFilterString, Qt::CaseInsensitive ) ) )
 
 
  739  if ( leftType != rightType )
 
  741    if ( leftType == QgsCoordinateReferenceSystemModelNode::NodeGroup )
 
  743    else if ( rightType == QgsCoordinateReferenceSystemModelNode::NodeGroup )
 
  747  const QString leftStr = sourceModel()->data( left ).toString().toLower();
 
  748  const QString rightStr = sourceModel()->data( right ).toString().toLower();
 
  750  if ( leftType == QgsCoordinateReferenceSystemModelNode::NodeGroup )
 
  755    if ( leftGroupId == QLatin1String( 
"USER" ) )
 
  757    if ( rightGroupId == QLatin1String( 
"USER" ) )
 
  760    if ( leftGroupId == QLatin1String( 
"CUSTOM" ) )
 
  762    if ( rightGroupId == QLatin1String( 
"CUSTOM" ) )
 
  767  return QString::localeAwareCompare( leftStr, rightStr ) < 0;
 
 
CrsType
Coordinate reference system types.
 
@ Compound
Compound (horizontal + vertical) CRS.
 
@ Projected
Projected CRS.
 
@ DerivedProjected
Derived projected CRS.
 
@ Engineering
Engineering CRS.
 
@ Geographic3d
3D geopraphic CRS
 
@ Geographic2d
2D geographic CRS
 
@ Geocentric
Geocentric CRS.
 
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
 
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
 
static QgsCoordinateReferenceSystemRegistry * coordinateReferenceSystemRegistry()
Returns the application's coordinate reference system (CRS) registry, which handles known CRS definit...
 
A tree model for display of known coordinate reference systems.
 
int rowCount(const QModelIndex &parent=QModelIndex()) const override
 
QModelIndex addCustomCrs(const QgsCoordinateReferenceSystem &crs)
Adds a custom crs to the model.
 
QModelIndex parent(const QModelIndex &index) const override
 
QgsCoordinateReferenceSystemModel(QObject *parent=nullptr)
Constructor for QgsCoordinateReferenceSystemModel, with the specified parent object.
 
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
 
QModelIndex authIdToIndex(const QString &authId) const
Retrieves the model index corresponding to a CRS with the specified authId.
 
@ Deprecated
true if the CRS is deprecated
 
@ AuthId
The coordinate reference system authority name and id.
 
@ Projection
Projection name.
 
@ GroupId
The node ID (for group nodes)
 
@ Name
The coordinate reference system name.
 
@ NodeType
Corresponds to the node's type.
 
@ Wkt
The coordinate reference system's WKT representation. This is only used for non-standard CRS (i....
 
@ Type
The coordinate reference system type.
 
@ Proj
The coordinate reference system's PROJ representation. This is only used for non-standard CRS (i....
 
QVariant data(const QModelIndex &index, int role) const override
 
Qt::ItemFlags flags(const QModelIndex &index) const override
 
int columnCount(const QModelIndex &=QModelIndex()) const override
 
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
 
QgsCoordinateReferenceSystemProxyModel(QObject *parent=nullptr)
Constructor for QgsCoordinateReferenceSystemProxyModel, with the given parent object.
 
void setFilterDeprecated(bool filter)
Sets whether deprecated CRS should be filtered from the results.
 
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override
 
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
 
Filters filters() const
Returns any filters that affect how CRS are filtered.
 
@ FilterVertical
Include vertical CRS (excludes compound CRS containing a vertical component)
 
@ FilterCompound
Include compound CRS.
 
@ FilterHorizontal
Include horizontal CRS (excludes compound CRS containing a horizontal component)
 
QgsCoordinateReferenceSystemModel * coordinateReferenceSystemModel()
Returns the underlying source model.
 
void setFilterString(const QString &filter)
Sets a filter string, such that only coordinate reference systems matching the specified string will ...
 
void setFilterAuthIds(const QSet< QString > &filter)
Sets a filter list of CRS auth ID strings, such that only coordinate reference systems matching the s...
 
void setFilters(QgsCoordinateReferenceSystemProxyModel::Filters filters)
Set filters that affect how CRS are filtered.
 
Contains details of a custom (user defined) CRS.
 
QList< QgsCrsDbRecord > crsDbRecords() const
Returns the list of records from the QGIS srs db.
 
void userCrsAdded(const QString &id)
Emitted whenever a new user CRS definition is added.
 
void userCrsChanged(const QString &id)
Emitted whenever an existing user CRS definition is changed.
 
void userCrsRemoved(long id)
Emitted when the user CRS with matching id is removed from the database.
 
QList< QgsCoordinateReferenceSystemRegistry::UserCrsDetails > userCrsList() const
Returns a list containing the details of all registered custom (user-defined) CRSes.
 
static QString translateProjection(const QString &projection)
Returns a translated string for a projection method.
 
Represents a coordinate reference system (CRS).
 
QString toProj() const
Returns a Proj string representation of this CRS.
 
QString toWkt(Qgis::CrsWktVariant variant=Qgis::CrsWktVariant::Wkt1Gdal, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
 
Qgis::CrsType type() const
Returns the type of the CRS.
 
static bool containsByWord(const QString &candidate, const QString &words, Qt::CaseSensitivity sensitivity=Qt::CaseInsensitive)
Given a candidate string, returns true if the candidate contains all the individual words from anothe...
 
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
 
#define BUILTIN_UNREACHABLE
 
const QgsCoordinateReferenceSystem & crs
 
QString projectionAcronym