QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgscoordinatereferencesystemmodel.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscoordinatereferencesystemmodel.h
3 -------------------
4 begin : July 2023
5 copyright : (C) 2023 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
18#include "moc_qgscoordinatereferencesystemmodel.cpp"
20#include "qgsapplication.h"
21#include "qgsstringutils.h"
22
23#include <QFont>
24
26 : QAbstractItemModel( parent )
27 , mRootNode( std::make_unique<QgsCoordinateReferenceSystemModelGroupNode>( QString(), QIcon(), QString() ) )
28{
30
31 rebuild();
32
33 connect( QgsApplication::coordinateReferenceSystemRegistry(), &QgsCoordinateReferenceSystemRegistry::userCrsAdded, this, &QgsCoordinateReferenceSystemModel::userCrsAdded );
34 connect( QgsApplication::coordinateReferenceSystemRegistry(), &QgsCoordinateReferenceSystemRegistry::userCrsRemoved, this, &QgsCoordinateReferenceSystemModel::userCrsRemoved );
35 connect( QgsApplication::coordinateReferenceSystemRegistry(), &QgsCoordinateReferenceSystemRegistry::userCrsChanged, this, &QgsCoordinateReferenceSystemModel::userCrsChanged );
36}
37
38Qt::ItemFlags QgsCoordinateReferenceSystemModel::flags( const QModelIndex &index ) const
39{
40 if ( !index.isValid() )
41 {
42 return Qt::ItemFlags();
43 }
44
45 QgsCoordinateReferenceSystemModelNode *n = index2node( index );
46 if ( !n )
47 return Qt::ItemFlags();
48
49 switch ( n->nodeType() )
50 {
51 case QgsCoordinateReferenceSystemModelNode::NodeGroup:
52 return index.column() == 0 ? Qt::ItemIsEnabled : Qt::ItemFlags();
53 case QgsCoordinateReferenceSystemModelNode::NodeCrs:
54 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
55 }
57}
58
59QVariant QgsCoordinateReferenceSystemModel::data( const QModelIndex &index, int role ) const
60{
61 if ( !index.isValid() )
62 return QVariant();
63
64 QgsCoordinateReferenceSystemModelNode *n = index2node( index );
65 if ( !n )
66 return QVariant();
67
68 if ( role == static_cast<int>( CustomRole::NodeType ) )
69 return n->nodeType();
70
71 switch ( n->nodeType() )
72 {
73 case QgsCoordinateReferenceSystemModelNode::NodeGroup:
74 {
75 QgsCoordinateReferenceSystemModelGroupNode *groupNode = qgis::down_cast<QgsCoordinateReferenceSystemModelGroupNode *>( n );
76 switch ( role )
77 {
78 case Qt::DecorationRole:
79 switch ( index.column() )
80 {
81 case 0:
82 return groupNode->icon();
83 default:
84 break;
85 }
86 break;
87
88 case Qt::DisplayRole:
89 case Qt::ToolTipRole:
90 switch ( index.column() )
91 {
92 case 0:
93 return groupNode->name();
94
95 default:
96 break;
97 }
98 break;
99
100 case Qt::FontRole:
101 {
102 QFont font;
103 font.setItalic( true );
104 if ( groupNode->parent() == mRootNode.get() )
105 {
106 font.setBold( true );
107 }
108 return font;
109 }
110
111 case static_cast<int>( CustomRole::GroupId ):
112 return groupNode->id();
113 }
114 return QVariant();
115 }
116 case QgsCoordinateReferenceSystemModelNode::NodeCrs:
117 {
118 QgsCoordinateReferenceSystemModelCrsNode *crsNode = qgis::down_cast<QgsCoordinateReferenceSystemModelCrsNode *>( n );
119 switch ( role )
120 {
121 case Qt::DisplayRole:
122 case Qt::ToolTipRole:
123 switch ( index.column() )
124 {
125 case 0:
126 return crsNode->record().description;
127
128 case 1:
129 {
130 if ( crsNode->record().authName == QLatin1String( "CUSTOM" ) )
131 return QString();
132 return QStringLiteral( "%1:%2" ).arg( crsNode->record().authName, crsNode->record().authId );
133 }
134
135 default:
136 break;
137 }
138 break;
139
140 case static_cast<int>( CustomRole::Name ):
141 return crsNode->record().description;
142
143 case static_cast<int>( CustomRole::AuthId ):
144 if ( !crsNode->record().authId.isEmpty() )
145 return QStringLiteral( "%1:%2" ).arg( crsNode->record().authName, crsNode->record().authId );
146 else
147 return QVariant();
148
149 case static_cast<int>( CustomRole::Deprecated ):
150 return crsNode->record().deprecated;
151
152 case static_cast<int>( CustomRole::Type ):
153 return QVariant::fromValue( crsNode->record().type );
154
155 case static_cast<int>( CustomRole::Wkt ):
156 return crsNode->wkt();
157
158 case static_cast<int>( CustomRole::Proj ):
159 return crsNode->proj();
160
161 case static_cast<int>( CustomRole::Group ):
162 return crsNode->group();
163
164 case static_cast<int>( CustomRole::Projection ):
165 return crsNode->projection();
166
167 default:
168 break;
169 }
170 }
171 }
172 return QVariant();
173}
174
175QVariant QgsCoordinateReferenceSystemModel::headerData( int section, Qt::Orientation orientation, int role ) const
176{
177 if ( orientation == Qt::Horizontal )
178 {
179 switch ( role )
180 {
181 case Qt::DisplayRole:
182 switch ( section )
183 {
184 case 0:
185 return tr( "Coordinate Reference System" );
186 case 1:
187 return tr( "Authority ID" );
188 default:
189 break;
190 }
191 break;
192
193 default:
194 break;
195 }
196 }
197 return QVariant();
198}
199
200int QgsCoordinateReferenceSystemModel::rowCount( const QModelIndex &parent ) const
201{
202 QgsCoordinateReferenceSystemModelNode *n = index2node( parent );
203 if ( !n )
204 return 0;
205
206 return n->children().count();
207}
208
210{
211 return 2;
212}
213
214QModelIndex QgsCoordinateReferenceSystemModel::index( int row, int column, const QModelIndex &parent ) const
215{
216 if ( !hasIndex( row, column, parent ) )
217 return QModelIndex();
218
219 QgsCoordinateReferenceSystemModelNode *n = index2node( parent );
220 if ( !n )
221 return QModelIndex(); // have no children
222
223 return createIndex( row, column, n->children().at( row ) );
224}
225
226QModelIndex QgsCoordinateReferenceSystemModel::parent( const QModelIndex &child ) const
227{
228 if ( !child.isValid() )
229 return QModelIndex();
230
231 if ( QgsCoordinateReferenceSystemModelNode *n = index2node( child ) )
232 {
233 return indexOfParentTreeNode( n->parent() ); // must not be null
234 }
235 else
236 {
237 Q_ASSERT( false ); // no other node types!
238 return QModelIndex();
239 }
240}
241
242QModelIndex QgsCoordinateReferenceSystemModel::authIdToIndex( const QString &authid ) const
243{
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 );
247}
248
249void QgsCoordinateReferenceSystemModel::rebuild()
250{
251 beginResetModel();
252
253 mRootNode->deleteChildren();
254
255 for ( const QgsCrsDbRecord &record : std::as_const( mCrsDbRecords ) )
256 {
257 addRecord( record );
258 }
259
260 const QList<QgsCoordinateReferenceSystemRegistry::UserCrsDetails> userCrsList = QgsApplication::coordinateReferenceSystemRegistry()->userCrsList();
261 for ( const QgsCoordinateReferenceSystemRegistry::UserCrsDetails &details : userCrsList )
262 {
263 QgsCrsDbRecord userRecord;
264 userRecord.authName = QStringLiteral( "USER" );
265 userRecord.authId = QString::number( details.id );
266 userRecord.description = details.name;
267
268 addRecord( userRecord );
269 }
270
271 endResetModel();
272}
273
274void QgsCoordinateReferenceSystemModel::userCrsAdded( const QString &id )
275{
276 const QList<QgsCoordinateReferenceSystemRegistry::UserCrsDetails> userCrsList = QgsApplication::coordinateReferenceSystemRegistry()->userCrsList();
277 for ( const QgsCoordinateReferenceSystemRegistry::UserCrsDetails &details : userCrsList )
278 {
279 if ( QStringLiteral( "USER:%1" ).arg( details.id ) == id )
280 {
281 QgsCrsDbRecord userRecord;
282 userRecord.authName = QStringLiteral( "USER" );
283 userRecord.authId = QString::number( details.id );
284 userRecord.description = details.name;
285
286 QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( "USER" ) );
287 if ( !group )
288 {
289 std::unique_ptr<QgsCoordinateReferenceSystemModelGroupNode> newGroup = std::make_unique<QgsCoordinateReferenceSystemModelGroupNode>(
290 tr( "User-defined" ),
291 QgsApplication::getThemeIcon( QStringLiteral( "/user.svg" ) ), QStringLiteral( "USER" )
292 );
293 beginInsertRows( QModelIndex(), mRootNode->children().length(), mRootNode->children().length() );
294 mRootNode->addChildNode( newGroup.get() );
295 endInsertRows();
296 group = newGroup.release();
297 }
298
299 const QModelIndex parentGroupIndex = node2index( group );
300
301 beginInsertRows( parentGroupIndex, group->children().size(), group->children().size() );
302 QgsCoordinateReferenceSystemModelCrsNode *crsNode = addRecord( userRecord );
303 crsNode->setProj( details.proj );
304 crsNode->setWkt( details.wkt );
305 endInsertRows();
306 break;
307 }
308 }
309}
310
311void QgsCoordinateReferenceSystemModel::userCrsRemoved( long id )
312{
313 QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( "USER" ) );
314 if ( group )
315 {
316 for ( int row = 0; row < group->children().size(); ++row )
317 {
318 if ( QgsCoordinateReferenceSystemModelCrsNode *crsNode = dynamic_cast<QgsCoordinateReferenceSystemModelCrsNode *>( group->children().at( row ) ) )
319 {
320 if ( crsNode->record().authId == QString::number( id ) )
321 {
322 const QModelIndex parentIndex = node2index( group );
323 beginRemoveRows( parentIndex, row, row );
324 delete group->takeChild( crsNode );
325 endRemoveRows();
326 return;
327 }
328 }
329 }
330 }
331}
332
333void QgsCoordinateReferenceSystemModel::userCrsChanged( const QString &id )
334{
335 QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( "USER" ) );
336 if ( group )
337 {
338 for ( int row = 0; row < group->children().size(); ++row )
339 {
340 if ( QgsCoordinateReferenceSystemModelCrsNode *crsNode = dynamic_cast<QgsCoordinateReferenceSystemModelCrsNode *>( group->children().at( row ) ) )
341 {
342 if ( QStringLiteral( "USER:%1" ).arg( crsNode->record().authId ) == id )
343 {
344 // treat a change as a remove + add operation
345 const QModelIndex parentIndex = node2index( group );
346 beginRemoveRows( parentIndex, row, row );
347 delete group->takeChild( crsNode );
348 endRemoveRows();
349
350 userCrsAdded( id );
351 return;
352 }
353 }
354 }
355 }
356}
357
358QgsCoordinateReferenceSystemModelCrsNode *QgsCoordinateReferenceSystemModel::addRecord( const QgsCrsDbRecord &record )
359{
360 QgsCoordinateReferenceSystemModelGroupNode *parentNode = mRootNode.get();
361 std::unique_ptr<QgsCoordinateReferenceSystemModelCrsNode> crsNode = std::make_unique<QgsCoordinateReferenceSystemModelCrsNode>( record );
362
363 QString groupName;
364 QString groupId;
365 QIcon groupIcon;
366 if ( record.authName == QLatin1String( "USER" ) )
367 {
368 groupName = tr( "User-defined" );
369 groupId = QStringLiteral( "USER" );
370 groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/user.svg" ) );
371 }
372 else if ( record.authName == QLatin1String( "CUSTOM" ) )
373 {
374 // the group is guaranteed to exist at this point
375 groupId = QStringLiteral( "CUSTOM" );
376 }
377 else
378 {
379 groupId = qgsEnumValueToKey( record.type );
380 switch ( record.type )
381 {
383 break;
385 groupName = tr( "Geodetic" );
386 groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconProjectionEnabled.svg" ) );
387 break;
389 groupName = tr( "Geocentric" );
390 groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconProjectionEnabled.svg" ) );
391 break;
393 groupName = tr( "Geographic (2D)" );
394 groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconProjectionEnabled.svg" ) );
395 break;
396
398 groupName = tr( "Geographic (3D)" );
399 groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/mIconProjectionEnabled.svg" ) );
400 break;
401
403 groupName = tr( "Vertical" );
404 break;
405
408 groupName = tr( "Projected" );
409 groupIcon = QgsApplication::getThemeIcon( QStringLiteral( "/transformed.svg" ) );
410 break;
411
413 groupName = tr( "Compound" );
414 break;
415
417 groupName = tr( "Temporal" );
418 break;
419
421 groupName = tr( "Engineering" );
422 break;
423
425 groupName = tr( "Bound" );
426 break;
427
429 groupName = tr( "Other" );
430 break;
431 }
432 }
433 crsNode->setGroup( groupName );
434
435 if ( QgsCoordinateReferenceSystemModelGroupNode *group = parentNode->getChildGroupNode( groupId ) )
436 {
437 parentNode = group;
438 }
439 else
440 {
441 std::unique_ptr<QgsCoordinateReferenceSystemModelGroupNode> newGroup = std::make_unique<QgsCoordinateReferenceSystemModelGroupNode>( groupName, groupIcon, groupId );
442 parentNode->addChildNode( newGroup.get() );
443 parentNode = newGroup.release();
444 }
445
446 if ( ( record.authName != QLatin1String( "USER" ) && record.authName != QLatin1String( "CUSTOM" ) ) && ( record.type == Qgis::CrsType::Projected || record.type == Qgis::CrsType::DerivedProjected ) )
447 {
449 if ( projectionName.isEmpty() )
450 projectionName = tr( "Other" );
451 else
452 crsNode->setProjection( projectionName );
453
454 if ( QgsCoordinateReferenceSystemModelGroupNode *group = parentNode->getChildGroupNode( record.projectionAcronym ) )
455 {
456 parentNode = group;
457 }
458 else
459 {
460 std::unique_ptr<QgsCoordinateReferenceSystemModelGroupNode> newGroup = std::make_unique<QgsCoordinateReferenceSystemModelGroupNode>( projectionName, QIcon(), record.projectionAcronym );
461 parentNode->addChildNode( newGroup.get() );
462 parentNode = newGroup.release();
463 }
464 }
465
466 parentNode->addChildNode( crsNode.get() );
467 return crsNode.release();
468}
469
471{
472 QgsCrsDbRecord userRecord;
473 userRecord.authName = QStringLiteral( "CUSTOM" );
474 userRecord.description = crs.description().isEmpty() ? tr( "Custom CRS" ) : crs.description();
475 userRecord.type = crs.type();
476
477 QgsCoordinateReferenceSystemModelGroupNode *group = mRootNode->getChildGroupNode( QStringLiteral( "CUSTOM" ) );
478 if ( !group )
479 {
480 std::unique_ptr<QgsCoordinateReferenceSystemModelGroupNode> newGroup = std::make_unique<QgsCoordinateReferenceSystemModelGroupNode>(
481 tr( "Custom" ),
482 QgsApplication::getThemeIcon( QStringLiteral( "/user.svg" ) ), QStringLiteral( "CUSTOM" )
483 );
484 beginInsertRows( QModelIndex(), mRootNode->children().length(), mRootNode->children().length() );
485 mRootNode->addChildNode( newGroup.get() );
486 endInsertRows();
487 group = newGroup.release();
488 }
489
490 const QModelIndex parentGroupIndex = node2index( group );
491
492 const int newRow = group->children().size();
493 beginInsertRows( parentGroupIndex, newRow, newRow );
494 QgsCoordinateReferenceSystemModelCrsNode *node = addRecord( userRecord );
495 node->setWkt( crs.toWkt( Qgis::CrsWktVariant::Preferred ) );
496 node->setProj( crs.toProj() );
497 endInsertRows();
498
499 return index( newRow, 0, parentGroupIndex );
500}
501
502QgsCoordinateReferenceSystemModelNode *QgsCoordinateReferenceSystemModel::index2node( const QModelIndex &index ) const
503{
504 if ( !index.isValid() )
505 return mRootNode.get();
506
507 return reinterpret_cast<QgsCoordinateReferenceSystemModelNode *>( index.internalPointer() );
508}
509
510QModelIndex QgsCoordinateReferenceSystemModel::node2index( QgsCoordinateReferenceSystemModelNode *node ) const
511{
512 if ( !node || !node->parent() )
513 return QModelIndex(); // this is the only root item -> invalid index
514
515 QModelIndex parentIndex = node2index( node->parent() );
516
517 int row = node->parent()->children().indexOf( node );
518 Q_ASSERT( row >= 0 );
519 return index( row, 0, parentIndex );
520}
521
522QModelIndex QgsCoordinateReferenceSystemModel::indexOfParentTreeNode( QgsCoordinateReferenceSystemModelNode *parentNode ) const
523{
524 Q_ASSERT( parentNode );
525
526 QgsCoordinateReferenceSystemModelNode *grandParentNode = parentNode->parent();
527 if ( !grandParentNode )
528 return QModelIndex(); // root node -> invalid index
529
530 int row = grandParentNode->children().indexOf( parentNode );
531 Q_ASSERT( row >= 0 );
532
533 return createIndex( row, 0, parentNode );
534}
535
537QgsCoordinateReferenceSystemModelNode::~QgsCoordinateReferenceSystemModelNode()
538{
539 qDeleteAll( mChildren );
540}
541
542QgsCoordinateReferenceSystemModelNode *QgsCoordinateReferenceSystemModelNode::takeChild( QgsCoordinateReferenceSystemModelNode *node )
543{
544 return mChildren.takeAt( mChildren.indexOf( node ) );
545}
546
547void QgsCoordinateReferenceSystemModelNode::addChildNode( QgsCoordinateReferenceSystemModelNode *node )
548{
549 if ( !node )
550 return;
551
552 Q_ASSERT( !node->mParent );
553 node->mParent = this;
554
555 mChildren.append( node );
556}
557
558void QgsCoordinateReferenceSystemModelNode::deleteChildren()
559{
560 qDeleteAll( mChildren );
561 mChildren.clear();
562}
563
564QgsCoordinateReferenceSystemModelGroupNode *QgsCoordinateReferenceSystemModelNode::getChildGroupNode( const QString &id )
565{
566 for ( QgsCoordinateReferenceSystemModelNode *node : std::as_const( mChildren ) )
567 {
568 if ( node->nodeType() == NodeGroup )
569 {
570 QgsCoordinateReferenceSystemModelGroupNode *groupNode = qgis::down_cast<QgsCoordinateReferenceSystemModelGroupNode *>( node );
571 if ( groupNode && groupNode->id() == id )
572 return groupNode;
573 }
574 }
575 return nullptr;
576}
577
578QgsCoordinateReferenceSystemModelGroupNode::QgsCoordinateReferenceSystemModelGroupNode( const QString &name, const QIcon &icon, const QString &id )
579 : mId( id )
580 , mName( name )
581 , mIcon( icon )
582{
583}
584
585QgsCoordinateReferenceSystemModelCrsNode::QgsCoordinateReferenceSystemModelCrsNode( const QgsCrsDbRecord &record )
586 : mRecord( record )
587{
588}
590
591
592//
593// QgsCoordinateReferenceSystemProxyModel
594//
595
597 : QSortFilterProxyModel( parent )
598 , mModel( new QgsCoordinateReferenceSystemModel( this ) )
599{
600 setSourceModel( mModel );
601 setDynamicSortFilter( true );
602 setSortLocaleAware( true );
603 setFilterCaseSensitivity( Qt::CaseInsensitive );
604 setRecursiveFilteringEnabled( true );
605 sort( 0 );
606}
607
612
617
619{
620 if ( mFilters == filters )
621 return;
622
623 mFilters = filters;
624 invalidateFilter();
625}
626
628{
629 mFilterString = filter;
630 invalidateFilter();
631}
632
634{
635 if ( mFilterAuthIds == filter )
636 return;
637
638 mFilterAuthIds.clear();
639 mFilterAuthIds.reserve( filter.size() );
640 for ( const QString &id : filter )
641 {
642 mFilterAuthIds.insert( id.toUpper() );
643 }
644 invalidateFilter();
645}
646
648{
649 if ( mFilterDeprecated == filter )
650 return;
651
652 mFilterDeprecated = filter;
653 invalidateFilter();
654}
655
656bool QgsCoordinateReferenceSystemProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
657{
658 if ( mFilterString.trimmed().isEmpty() && !mFilters && !mFilterDeprecated && mFilterAuthIds.isEmpty() )
659 return true;
660
661 const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
662 const QgsCoordinateReferenceSystemModelNode::NodeType nodeType = static_cast<QgsCoordinateReferenceSystemModelNode::NodeType>( sourceModel()->data( sourceIndex, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::NodeType ) ).toInt() );
663 switch ( nodeType )
664 {
665 case QgsCoordinateReferenceSystemModelNode::NodeGroup:
666 return false;
667 case QgsCoordinateReferenceSystemModelNode::NodeCrs:
668 break;
669 }
670
671 const bool deprecated = sourceModel()->data( sourceIndex, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Deprecated ) ).toBool();
672 if ( mFilterDeprecated && deprecated )
673 return false;
674
675 if ( mFilters )
676 {
677 const Qgis::CrsType type = sourceModel()->data( sourceIndex, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Type ) ).value<Qgis::CrsType>();
678 switch ( type )
679 {
682 break;
683
693 if ( !mFilters.testFlag( Filter::FilterHorizontal ) )
694 return false;
695 break;
696
698 if ( !mFilters.testFlag( Filter::FilterVertical ) )
699 return false;
700 break;
701
703 if ( !mFilters.testFlag( Filter::FilterCompound ) )
704 return false;
705 break;
706 }
707 }
708
709 const QString authid = sourceModel()->data( sourceIndex, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
710 if ( !mFilterAuthIds.isEmpty() )
711 {
712 if ( !mFilterAuthIds.contains( authid.toUpper() ) )
713 return false;
714 }
715
716 if ( !mFilterString.trimmed().isEmpty() )
717 {
718 const QString name = sourceModel()->data( sourceIndex, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Name ) ).toString();
719 QString candidate = name;
720 const QString groupName = sourceModel()->data( sourceIndex, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Group ) ).toString();
721 if ( !groupName.isEmpty() )
722 candidate += ' ' + groupName;
723 const QString projectionName = sourceModel()->data( sourceIndex, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Projection ) ).toString();
724 if ( !projectionName.isEmpty() )
725 candidate += ' ' + projectionName;
726
727 if ( !( QgsStringUtils::containsByWord( candidate, mFilterString )
728 || authid.contains( mFilterString, Qt::CaseInsensitive ) ) )
729 return false;
730 }
731 return true;
732}
733
734bool QgsCoordinateReferenceSystemProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const
735{
736 QgsCoordinateReferenceSystemModelNode::NodeType leftType = static_cast<QgsCoordinateReferenceSystemModelNode::NodeType>( sourceModel()->data( left, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::NodeType ) ).toInt() );
737 QgsCoordinateReferenceSystemModelNode::NodeType rightType = static_cast<QgsCoordinateReferenceSystemModelNode::NodeType>( sourceModel()->data( right, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::NodeType ) ).toInt() );
738
739 if ( leftType != rightType )
740 {
741 if ( leftType == QgsCoordinateReferenceSystemModelNode::NodeGroup )
742 return true;
743 else if ( rightType == QgsCoordinateReferenceSystemModelNode::NodeGroup )
744 return false;
745 }
746
747 const QString leftStr = sourceModel()->data( left ).toString().toLower();
748 const QString rightStr = sourceModel()->data( right ).toString().toLower();
749
750 if ( leftType == QgsCoordinateReferenceSystemModelNode::NodeGroup )
751 {
752 // both are groups -- ensure USER group comes last, and CUSTOM group comes first
753 const QString leftGroupId = sourceModel()->data( left, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::GroupId ) ).toString();
754 const QString rightGroupId = sourceModel()->data( left, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::GroupId ) ).toString();
755 if ( leftGroupId == QLatin1String( "USER" ) )
756 return false;
757 if ( rightGroupId == QLatin1String( "USER" ) )
758 return true;
759
760 if ( leftGroupId == QLatin1String( "CUSTOM" ) )
761 return true;
762 if ( rightGroupId == QLatin1String( "CUSTOM" ) )
763 return false;
764 }
765
766 // default sort is alphabetical order
767 return QString::localeAwareCompare( leftStr, rightStr ) < 0;
768}
CrsType
Coordinate reference system types.
Definition qgis.h:2222
@ Vertical
Vertical CRS.
@ Temporal
Temporal CRS.
@ Compound
Compound (horizontal + vertical) CRS.
@ Projected
Projected CRS.
@ Other
Other type.
@ Bound
Bound CRS.
@ DerivedProjected
Derived projected CRS.
@ Unknown
Unknown type.
@ Engineering
Engineering CRS.
@ Geographic3d
3D geopraphic CRS
@ Geodetic
Geodetic 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.
@ 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)
@ 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.
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.
This class 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.
Definition qgis.h:6257
#define BUILTIN_UNREACHABLE
Definition qgis.h:6720
const QgsCoordinateReferenceSystem & crs