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