QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsprojectionselectionwidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsprojectionselectionwidget.cpp
3 --------------------------------------
4 Date : 05.01.2015
5 Copyright : (C) 2015 Denis Rouzaud
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include <QHBoxLayout>
17
19#include "moc_qgsprojectionselectionwidget.cpp"
20#include "qgsapplication.h"
22#include "qgsproject.h"
23#include "qgssettings.h"
27#include "qgsdatums.h"
28
29#ifdef ENABLE_MODELTEST
30#include "modeltest.h"
31#endif
32
33
35StandardCoordinateReferenceSystemsModel::StandardCoordinateReferenceSystemsModel( QObject *parent )
36 : QAbstractItemModel( parent )
37 , mProjectCrs( QgsProject::instance()->crs() )
38{
39#ifdef ENABLE_MODELTEST
40 new ModelTest( this, this );
41#endif
42
43 const QgsSettings settings;
44 mDefaultCrs = QgsCoordinateReferenceSystem( settings.value( QStringLiteral( "/projections/defaultProjectCrs" ), geoEpsgCrsAuthId(), QgsSettings::App ).toString() );
45
47 mCurrentCrs.updateDefinition();
48 mLayerCrs.updateDefinition();
49 mProjectCrs.updateDefinition();
50 mDefaultCrs.updateDefinition();
51 } );
52}
53
54Qt::ItemFlags StandardCoordinateReferenceSystemsModel::flags( const QModelIndex &index ) const
55{
56 if ( !index.isValid() )
57 {
58 return Qt::ItemFlags();
59 }
60
61 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
62}
63
64QVariant StandardCoordinateReferenceSystemsModel::data( const QModelIndex &index, int role ) const
65{
66 const QgsProjectionSelectionWidget::CrsOption option = optionForIndex( index );
68 return QVariant();
69
70 const QgsCoordinateReferenceSystem crs = StandardCoordinateReferenceSystemsModel::crs( index );
71 switch ( role )
72 {
73 case Qt::DisplayRole:
74 case Qt::ToolTipRole:
75 switch ( option )
76 {
78 return tr( "Project CRS: %1" ).arg( crs.userFriendlyIdentifier() );
80 return tr( "Default CRS: %1" ).arg( crs.userFriendlyIdentifier() );
82 return tr( "Layer CRS: %1" ).arg( crs.userFriendlyIdentifier() );
84 return mNotSetText;
89 break;
90 }
91 break;
92
93 case RoleCrs:
94 return crs;
95
96 case RoleOption:
97 return static_cast<int>( option );
98
99 default:
100 break;
101 }
102
103 return QVariant();
104}
105
106int StandardCoordinateReferenceSystemsModel::rowCount( const QModelIndex &parent ) const
107{
108 if ( parent.isValid() )
109 return 0;
110
111 return 5;
112}
113
114int StandardCoordinateReferenceSystemsModel::columnCount( const QModelIndex & ) const
115{
116 return 1;
117}
118
119QModelIndex StandardCoordinateReferenceSystemsModel::index( int row, int column, const QModelIndex &parent ) const
120{
121 if ( row < 0 || row >= rowCount() || column != 0 || parent.isValid() )
122 return QModelIndex();
123
124 return createIndex( row, column );
125}
126
127QModelIndex StandardCoordinateReferenceSystemsModel::parent( const QModelIndex & ) const
128{
129 return QModelIndex();
130}
131
132QgsCoordinateReferenceSystem StandardCoordinateReferenceSystemsModel::crs( const QModelIndex &index ) const
133{
134 if ( !index.isValid() )
136
137 const QgsProjectionSelectionWidget::CrsOption option = optionForIndex( index );
138 switch ( option )
139 {
141 return mProjectCrs;
143 return mDefaultCrs;
145 return mCurrentCrs;
147 return mLayerCrs;
152 }
154}
155
156QgsProjectionSelectionWidget::CrsOption StandardCoordinateReferenceSystemsModel::optionForIndex( const QModelIndex &index ) const
157{
158 if ( !index.isValid() )
160
161 const int row = index.row();
162 switch ( row )
163 {
164 case 0:
166 case 1:
168 case 2:
170 case 3:
172 case 4:
174 default:
175 break;
176 }
177
179}
180
181QModelIndex StandardCoordinateReferenceSystemsModel::indexForOption( QgsProjectionSelectionWidget::CrsOption option ) const
182{
183 int row = 0;
184 switch ( option )
185 {
188 return QModelIndex();
190 row = 0;
191 break;
193 row = 1;
194 break;
196 row = 2;
197 break;
199 row = 3;
200 break;
202 row = 4;
203 break;
204 }
205
206 return index( row, 0, QModelIndex() );
207}
208
209void StandardCoordinateReferenceSystemsModel::setLayerCrs( const QgsCoordinateReferenceSystem &crs )
210{
211 mLayerCrs = crs;
212 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::LayerCrs );
213 emit dataChanged( index, index );
214}
215
216void StandardCoordinateReferenceSystemsModel::setCurrentCrs( const QgsCoordinateReferenceSystem &crs )
217{
218 mCurrentCrs = crs;
219 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::LayerCrs );
220 emit dataChanged( index, index );
221}
222
223void StandardCoordinateReferenceSystemsModel::setNotSetText( const QString &text )
224{
225 mNotSetText = text;
226 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::CrsNotSet );
227 emit dataChanged( index, index );
228}
229
230//
231// CombinedCoordinateReferenceSystemsModel
232//
233
234CombinedCoordinateReferenceSystemsModel::CombinedCoordinateReferenceSystemsModel( QObject *parent )
235 : QConcatenateTablesProxyModel( parent )
236 , mStandardModel( new StandardCoordinateReferenceSystemsModel( this ) )
237 , mRecentModel( new QgsRecentCoordinateReferenceSystemsProxyModel( this ) )
238{
239 addSourceModel( mStandardModel );
240 addSourceModel( mRecentModel );
241}
242
243void CombinedCoordinateReferenceSystemsModel::setNotSetText( const QString &text )
244{
245 mStandardModel->setNotSetText( text );
246}
247
248QString CombinedCoordinateReferenceSystemsModel::notSetText() const
249{
250 return mStandardModel->notSetText();
251}
252
253QgsCoordinateReferenceSystem CombinedCoordinateReferenceSystemsModel::currentCrs() const
254{
255 return mStandardModel->currentCrs();
256}
257
258//
259// CombinedCoordinateReferenceSystemsProxyModel
260//
261CombinedCoordinateReferenceSystemsProxyModel::CombinedCoordinateReferenceSystemsProxyModel( QObject *parent )
262 : QSortFilterProxyModel( parent )
263 , mModel( new CombinedCoordinateReferenceSystemsModel( this ) )
264{
265 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::CurrentCrs, true );
266 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::ProjectCrs, true );
267 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::DefaultCrs, true );
268
269 setSourceModel( mModel );
270 setDynamicSortFilter( true );
271}
272
273bool CombinedCoordinateReferenceSystemsProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
274{
275 const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
276
277 const QgsCoordinateReferenceSystem crs = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
278 if ( !mFilteredCrs.isEmpty() && !mFilteredCrs.contains( crs ) )
279 return false;
280
281 switch ( crs.type() )
282 {
285 break;
286
297 return false;
298 break;
299
302 return false;
303 break;
304
307 return false;
308 break;
309 }
310
311 const QVariant optionInt = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleOption );
312 if ( optionInt.isValid() )
313 {
314 if ( optionInt.toInt() > 0 )
315 {
316 const QgsProjectionSelectionWidget::CrsOption option = static_cast<QgsProjectionSelectionWidget::CrsOption>( optionInt.toInt() );
317 if ( !mVisibleOptions.testFlag( option ) )
318 return false;
319
320 // specific logic for showing/hiding options:
321 switch ( option )
322 {
324 break;
325
328 // only show these options if the crs is valid
329 return crs.isValid();
330
332 // hide invalid current CRS value option only if "not set" option is shown
333 return crs.isValid() || !mVisibleOptions.testFlag( QgsProjectionSelectionWidget::CrsNotSet );
334
338 // always shown
339 break;
340 }
341 return true;
342 }
343 }
344 else
345 {
346 // a recent crs
347 // these are only shown if they aren't duplicates of a standard item already shown in the list
348 for ( QgsProjectionSelectionWidget::CrsOption standardOption :
349 {
354 } )
355 {
356 const QModelIndexList standardItemIndex = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption, static_cast<int>( standardOption ) );
357 if ( standardItemIndex.empty() )
358 continue;
359
360 const QgsCoordinateReferenceSystem standardItemCrs = mModel->data( standardItemIndex.at( 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
361 if ( standardItemCrs == crs && filterAcceptsRow( standardItemIndex.at( 0 ).row(), QModelIndex() ) )
362 return false;
363 }
364 }
365
366 return true;
367}
368
369void CombinedCoordinateReferenceSystemsProxyModel::setLayerCrs( const QgsCoordinateReferenceSystem &crs )
370{
371 mModel->standardModel()->setLayerCrs( crs );
372 invalidateFilter();
373}
374
375void CombinedCoordinateReferenceSystemsProxyModel::setCurrentCrs( const QgsCoordinateReferenceSystem &crs )
376{
377 mModel->standardModel()->setCurrentCrs( crs );
378 invalidateFilter();
379}
380
381void CombinedCoordinateReferenceSystemsProxyModel::setFilters( QgsCoordinateReferenceSystemProxyModel::Filters filters )
382{
383 mFilters = filters;
384 invalidateFilter();
385}
386
387QgsCoordinateReferenceSystemProxyModel::Filters CombinedCoordinateReferenceSystemsProxyModel::filters() const
388{
389 return mFilters;
390}
391
392void CombinedCoordinateReferenceSystemsProxyModel::setFilteredCrs( const QList<QgsCoordinateReferenceSystem> &crses )
393{
394 mFilteredCrs = crses;
395 invalidateFilter();
396}
397
398void CombinedCoordinateReferenceSystemsProxyModel::setOption( QgsProjectionSelectionWidget::CrsOption option, bool enabled )
399{
400 mVisibleOptions.setFlag( option, enabled );
401 invalidateFilter();
402}
403
405
406
408 : QWidget( parent )
409 , mDialogTitle( tr( "Coordinate Reference System Selector" ) )
410{
411 mCrsComboBox = new QgsHighlightableComboBox( this );
412 mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
413
414 mModel = new CombinedCoordinateReferenceSystemsProxyModel( this );
415 mModel->setFilters( filters );
416 mCrsComboBox->setModel( mModel );
417
418 const int labelMargin = static_cast<int>( std::round( mCrsComboBox->fontMetrics().horizontalAdvance( 'X' ) ) );
419 QHBoxLayout *layout = new QHBoxLayout();
420 layout->setContentsMargins( 0, 0, 0, 0 );
421 layout->setSpacing( 0 );
422 setLayout( layout );
423
424 layout->addWidget( mCrsComboBox, 1 );
425
426 // bit of fiddlyness here -- we want the initial spacing to only be visible
427 // when the warning label is shown, so it's embedded inside mWarningLabel
428 // instead of outside it
429 mWarningLabelContainer = new QWidget();
430 QHBoxLayout *warningLayout = new QHBoxLayout();
431 warningLayout->setContentsMargins( 0, 0, 0, 0 );
432 mWarningLabel = new QLabel();
433 const QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "mIconWarning.svg" ) );
434 const int size = static_cast<int>( std::max( 24.0, mCrsComboBox->minimumSize().height() * 0.5 ) );
435 mWarningLabel->setPixmap( icon.pixmap( icon.actualSize( QSize( size, size ) ) ) );
436 warningLayout->insertSpacing( 0, labelMargin / 2 );
437 warningLayout->insertWidget( 1, mWarningLabel );
438 mWarningLabelContainer->setLayout( warningLayout );
439 layout->addWidget( mWarningLabelContainer );
440 mWarningLabelContainer->hide();
441
442 layout->addSpacing( labelMargin / 2 );
443
444 mButton = new QToolButton( this );
445 mButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionSetProjection.svg" ) ) );
446 mButton->setToolTip( tr( "Select CRS" ) );
447 layout->addWidget( mButton );
448
449 setFocusPolicy( Qt::StrongFocus );
450 setFocusProxy( mButton );
451 setAcceptDrops( true );
452
453 connect( mButton, &QToolButton::clicked, this, &QgsProjectionSelectionWidget::selectCrs );
454 connect( mCrsComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsProjectionSelectionWidget::comboIndexChanged );
455}
456
458{
459 const int idx = mCrsComboBox->currentIndex();
460 if ( idx >= 0 && idx < mModel->rowCount() )
461 return mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
462 else
464}
465
467{
468 switch ( option )
469 {
474 {
475 mModel->setOption( option, visible );
476 updateTooltip();
477 return;
478 }
480 //recently used CRS option cannot be readded
481 return;
483 {
484 mModel->setOption( CrsNotSet, visible );
485
486 if ( !visible )
487 {
489 }
490 else
491 {
492 if ( !mModel->combinedModel()->currentCrs().isValid() )
493 whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
494 }
495 updateTooltip();
496
497 return;
498 }
499 case Invalid:
500 return;
501 }
502}
503
505{
506 mModel->combinedModel()->setNotSetText( text );
507}
508
510{
511 mMessage = text;
512}
513
515{
516 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption, static_cast<int>( option ) );
517 return !matches.empty();
518}
519
521{
523 const QList<QgsCoordinateReferenceSystem> filteredCrses = mModel->filteredCrs();
524
525 QSet<QString> ogcFilter;
526 ogcFilter.reserve( filteredCrses.size() );
527 for ( const QgsCoordinateReferenceSystem &crs : std::as_const( filteredCrses ) )
528 {
529 ogcFilter << crs.authid();
530 }
531
532 if ( panel && panel->dockMode() )
533 {
534 mActivePanel = new QgsCrsSelectionWidget( this, mModel->filters() );
535 if ( !ogcFilter.isEmpty() )
536 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
537 if ( !mMessage.isEmpty() )
538 mActivePanel->setMessage( mMessage );
539 mActivePanel->setCrs( crs() );
540
541 if ( !mModel->combinedModel()->notSetText().isEmpty() )
542 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
543
544 mActivePanel->setPanelTitle( mDialogTitle );
545
547 {
548 mActivePanel->setShowNoCrs( true );
549 }
550
551 connect( mActivePanel, &QgsCrsSelectionWidget::crsChanged, this, [this] {
552 if ( mIgnorePanelSignals )
553 return;
554
555 if ( !mActivePanel->hasValidSelection() )
556 return;
557
558 mCrsComboBox->blockSignals( true );
559 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
560 mCrsComboBox->blockSignals( false );
561 const QgsCoordinateReferenceSystem crs = mActivePanel->crs();
562
563 mIgnorePanelSignals++;
564 setCrs( crs );
565 mIgnorePanelSignals--;
566
567 emit crsChanged( crs );
568 } );
569 panel->openPanel( mActivePanel );
570 }
571 else
572 {
573 QgsProjectionSelectionDialog dlg( this, QgsGuiUtils::ModalDialogFlags, mModel->filters() );
574 if ( !mMessage.isEmpty() )
575 dlg.setMessage( mMessage );
576 if ( !ogcFilter.isEmpty() )
577 dlg.setOgcWmsCrsFilter( ogcFilter );
578 dlg.setCrs( crs() );
579 dlg.setWindowTitle( mDialogTitle );
580
581 if ( !mModel->combinedModel()->notSetText().isEmpty() )
582 dlg.setNotSetText( mModel->combinedModel()->notSetText() );
583
585 {
586 dlg.setShowNoProjection( true );
587 }
589
590 if ( dlg.exec() )
591 {
592 mCrsComboBox->blockSignals( true );
593 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
594 mCrsComboBox->blockSignals( false );
596 // setCrs will emit crsChanged for us
597 setCrs( crs );
598 }
599 else
600 {
601 QApplication::restoreOverrideCursor();
602 }
603 }
604}
605
607{
608 if ( !( event->possibleActions() & Qt::CopyAction ) )
609 {
610 event->ignore();
611 return;
612 }
613
614 if ( mapLayerFromMimeData( event->mimeData() ) )
615 {
616 // dragged an acceptable layer, phew
617 event->setDropAction( Qt::CopyAction );
618 event->accept();
619 mCrsComboBox->setHighlighted( true );
620 update();
621 }
622 else
623 {
624 event->ignore();
625 }
626}
627
629{
630 if ( mCrsComboBox->isHighlighted() )
631 {
632 event->accept();
633 mCrsComboBox->setHighlighted( false );
634 update();
635 }
636 else
637 {
638 event->ignore();
639 }
640}
641
643{
644 if ( !( event->possibleActions() & Qt::CopyAction ) )
645 {
646 event->ignore();
647 return;
648 }
649
650 if ( QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
651 {
652 // dropped a map layer
653 setFocus( Qt::MouseFocusReason );
654 event->setDropAction( Qt::CopyAction );
655 event->accept();
656
657 if ( layer->crs().isValid() )
658 setCrs( layer->crs() );
659 }
660 else
661 {
662 event->ignore();
663 }
664 mCrsComboBox->setHighlighted( false );
665 update();
666}
667
669{
670 return mSourceEnsemble;
671}
672
674{
675 mDialogTitle = title;
676}
677
679{
680 return mDialogTitle;
681}
682
683void QgsProjectionSelectionWidget::setFilter( const QList<QgsCoordinateReferenceSystem> &crses )
684{
685 mModel->setFilteredCrs( crses );
686}
687
692
694{
695 mModel->setFilters( filters );
696 if ( mActivePanel )
697 mActivePanel->setFilters( filters );
698}
699
701{
702 if ( mSourceEnsemble == ensemble )
703 return;
704
705 mSourceEnsemble = ensemble;
706 updateWarning();
707}
708
710{
711 return mShowAccuracyWarnings;
712}
713
715{
716 mShowAccuracyWarnings = show;
717 if ( !mShowAccuracyWarnings )
718 mWarningLabelContainer->hide();
719 else
720 updateWarning();
721}
722
723void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
724{
725 if ( idx >= 0 && idx < mModel->rowCount() )
726 {
727 const QgsCoordinateReferenceSystem crs = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
728 const QVariant optionData = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption );
729 if ( !optionData.isValid() || static_cast<CrsOption>( optionData.toInt() ) != QgsProjectionSelectionWidget::CrsNotSet )
730 {
731 // RoleOption is only available for items from the standard coordinate reference system model, but we
732 // are using a combined model which also has items from QgsRecentCoordinateReferenceSystemsModel
733 emit crsChanged( crs );
734 }
735 else
736 {
737 emit cleared();
739 }
740 }
741
742 updateTooltip();
743}
744
745void QgsProjectionSelectionWidget::updateWarning()
746{
747 if ( !mShowAccuracyWarnings )
748 {
749 if ( mWarningLabelContainer->isVisible() )
750 mWarningLabelContainer->hide();
751 return;
752 }
753
754 try
755 {
756 const double crsAccuracyWarningThreshold = QgsSettings().value( QStringLiteral( "/projections/crsAccuracyWarningThreshold" ), 0.0, QgsSettings::App ).toDouble();
757
758 const QgsDatumEnsemble ensemble = crs().datumEnsemble();
759 if ( !ensemble.isValid() || ensemble.name() == mSourceEnsemble || ( ensemble.accuracy() > 0 && ensemble.accuracy() < crsAccuracyWarningThreshold ) )
760 {
761 mWarningLabelContainer->hide();
762 }
763 else
764 {
765 mWarningLabelContainer->show();
766
767 QString warning = QStringLiteral( "<p>" );
768
769 QString id;
770 if ( !ensemble.code().isEmpty() )
771 id = QStringLiteral( "<i>%1</i> (%2:%3)" ).arg( ensemble.name(), ensemble.authority(), ensemble.code() );
772 else
773 id = QStringLiteral( "<i>%</i>”" ).arg( ensemble.name() );
774
775 if ( ensemble.accuracy() > 0 )
776 {
777 warning = tr( "The selected CRS is based on %1, which has a limited accuracy of <b>at best %2 meters</b>." ).arg( id ).arg( ensemble.accuracy() );
778 }
779 else
780 {
781 warning = tr( "The selected CRS is based on %1, which has a limited accuracy." ).arg( id );
782 }
783 warning += QStringLiteral( "</p><p>" ) + tr( "Use an alternative CRS if accurate positioning is required." ) + QStringLiteral( "</p>" );
784
785 const QList<QgsDatumEnsembleMember> members = ensemble.members();
786 if ( !members.isEmpty() )
787 {
788 warning += QStringLiteral( "<p>" ) + tr( "%1 consists of the datums:" ).arg( ensemble.name() ) + QStringLiteral( "</p><ul>" );
789
790 for ( const QgsDatumEnsembleMember &member : members )
791 {
792 if ( !member.code().isEmpty() )
793 id = QStringLiteral( "%1 (%2:%3)" ).arg( member.name(), member.authority(), member.code() );
794 else
795 id = member.name();
796 warning += QStringLiteral( "<li>%1</li>" ).arg( id );
797 }
798
799 warning += QLatin1String( "</ul>" );
800 }
801
802 mWarningLabel->setToolTip( warning );
803 }
804 }
805 catch ( QgsNotSupportedException & )
806 {
807 mWarningLabelContainer->hide();
808 }
809}
810
812{
813 const QgsCoordinateReferenceSystem prevCrs = mModel->combinedModel()->currentCrs();
814 mModel->setCurrentCrs( crs );
815
816 if ( crs.isValid() )
817 {
819 mCrsComboBox->blockSignals( true );
820 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
821 mCrsComboBox->blockSignals( false );
822 }
823 else
824 {
825 const int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet, StandardCoordinateReferenceSystemsModel::Role::RoleOption );
826 if ( crsNotSetIndex >= 0 )
827 {
828 mCrsComboBox->blockSignals( true );
829 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
830 mCrsComboBox->blockSignals( false );
831 }
832 }
833 if ( mActivePanel && !mIgnorePanelSignals )
834 {
835 mIgnorePanelSignals++;
836 mActivePanel->setCrs( crs );
837 mIgnorePanelSignals--;
838 }
839 if ( prevCrs != crs )
840 {
841 emit crsChanged( crs );
842 }
843 updateTooltip();
844}
845
847{
848 mModel->setLayerCrs( crs );
849}
850
852{
853 if ( crs.isValid() )
855 else
856 return tr( "invalid projection" );
857}
858
859void QgsProjectionSelectionWidget::updateTooltip()
860{
862 if ( c.isValid() )
863 setToolTip( c.toWkt( Qgis::CrsWktVariant::Preferred, true ) );
864 else
865 setToolTip( QString() );
866 updateWarning();
867}
868
869QgsMapLayer *QgsProjectionSelectionWidget::mapLayerFromMimeData( const QMimeData *data ) const
870{
872 for ( const QgsMimeDataUtils::Uri &u : uriList )
873 {
874 // is this uri from the current project?
875 if ( QgsMapLayer *layer = u.mapLayer() )
876 {
877 return layer;
878 }
879 }
880 return nullptr;
881}
@ 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...
@ FilterVertical
Include vertical CRS (excludes compound CRS containing a vertical component)
@ FilterHorizontal
Include horizontal CRS (excludes compound CRS containing a horizontal component)
void userCrsChanged(const QString &id)
Emitted whenever an existing user CRS definition is changed.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QString userFriendlyIdentifier(Qgis::CrsIdentifierType type=Qgis::CrsIdentifierType::MediumString) const
Returns a user friendly identifier for the CRS.
QgsDatumEnsemble datumEnsemble() const
Attempts to retrieve datum ensemble details from the CRS.
Qgis::CrsType type() const
Returns the type of the CRS.
A generic widget allowing users to pick a Coordinate Reference System (or define their own).
void crsChanged()
Emitted when the CRS defined in the widget is changed.
Contains information about a member of a datum ensemble.
Definition qgsdatums.h:35
Contains information about a datum ensemble.
Definition qgsdatums.h:95
QString code() const
Identification code, e.g.
Definition qgsdatums.h:122
QString authority() const
Authority name, e.g.
Definition qgsdatums.h:117
bool isValid() const
Returns true if the datum ensemble is a valid object, or false if it is a null/invalid object.
Definition qgsdatums.h:102
QList< QgsDatumEnsembleMember > members() const
Contains a list of members of the ensemble.
Definition qgsdatums.h:137
QString name() const
Display name of datum ensemble.
Definition qgsdatums.h:107
double accuracy() const
Positional accuracy (in meters).
Definition qgsdatums.h:112
A QComboBox subclass with the ability to "highlight" the edges of the widget.
void setHighlighted(bool highlighted)
Sets whether the combo box is currently highlighted.
bool isHighlighted() const
Returns true if the combo box is currently highlighted.
Base class for all map layer types.
Definition qgsmaplayer.h:76
QList< QgsMimeDataUtils::Uri > UriList
static UriList decodeUriList(const QMimeData *data)
Custom exception class which is raised when an operation is not supported.
Base class for any widget that can be shown as a inline panel.
void openPanel(QgsPanelWidget *panel)
Open a panel or dialog depending on dock mode setting If dock mode is true this method will emit the ...
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
bool dockMode()
Returns the dock mode state.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:107
A generic dialog to prompt the user for a Coordinate Reference System.
void setShowNoProjection(bool show)
Sets whether a "no/invalid" projection option should be shown.
void setNotSetText(const QString &text, const QString &description=QString())
Sets the text to show for the not set option.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the initial crs to show within the dialog.
void setMessage(const QString &message)
Sets a message to show in the dialog.
QgsCoordinateReferenceSystem crs() const
Returns the CRS currently selected in the widget.
void setRequireValidSelection()
Sets the dialog to require a valid selection only, preventing users from accepting the dialog if no s...
void setOgcWmsCrsFilter(const QSet< QString > &crsFilter)
filters this dialog by the given CRSs
void setFilter(const QList< QgsCoordinateReferenceSystem > &crses)
Sets a filtered list of CRSes to show in the widget.
bool showAccuracyWarnings() const
Returns true if the widget will show a warning to users when they select a CRS which has low accuracy...
void cleared()
Emitted when the not set option is selected.
void selectCrs()
Opens the dialog for selecting a new CRS.
CrsOption
Predefined CRS options shown in widget.
@ CrsNotSet
Not set (hidden by default)
@ ProjectCrs
Current project CRS (if OTF reprojection enabled)
@ Invalid
Invalid option, since QGIS 3.36.
@ CurrentCrs
Current user selected CRS.
bool optionVisible(CrsOption option) const
Returns whether the specified CRS option is visible in the widget.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the current CRS for the widget.
void setNotSetText(const QString &text)
Sets the text to show for the not set option.
void setLayerCrs(const QgsCoordinateReferenceSystem &crs)
Sets the layer CRS for the widget.
void setOptionVisible(CrsOption option, bool visible)
Sets whether a predefined CRS option should be shown in the widget.
QString sourceEnsemble() const
Returns the original source ensemble datum name.
QgsCoordinateReferenceSystem crs() const
Returns the currently selected CRS for the widget.
QString dialogTitle() const
Returns the title for the CRS selector dialog window.
void setFilters(QgsCoordinateReferenceSystemProxyModel::Filters filters)
Sets filters for the available CRS.
void dragEnterEvent(QDragEnterEvent *event) override
void setMessage(const QString &text)
Sets a message to show in the dialog.
static QString crsOptionText(const QgsCoordinateReferenceSystem &crs)
Returns display text for the specified crs.
void dragLeaveEvent(QDragLeaveEvent *event) override
void setShowAccuracyWarnings(bool show)
Sets whether the widget will show warnings to users when they select a CRS which has low accuracy.
void setDialogTitle(const QString &title)
Sets the title for the CRS selector dialog window.
void crsChanged(const QgsCoordinateReferenceSystem &crs)
Emitted when the selected CRS is changed.
void setSourceEnsemble(const QString &ensemble)
Sets the original source ensemble datum name.
QgsCoordinateReferenceSystemProxyModel::Filters filters() const
Returns the filters set on the available CRS.
QgsProjectionSelectionWidget(QWidget *parent=nullptr, QgsCoordinateReferenceSystemProxyModel::Filters filters=QgsCoordinateReferenceSystemProxyModel::FilterHorizontal|QgsCoordinateReferenceSystemProxyModel::FilterCompound)
Constructor for QgsProjectionSelectionWidget, with the specified parent widget.
void dropEvent(QDropEvent *event) override
A sort/filter proxy model for recent coordinate reference systems.
This class is a composition of two QSettings instances:
Definition qgssettings.h:64
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define BUILTIN_UNREACHABLE
Definition qgis.h:6720
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:5970
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
Definition qgis.h:6555
const QgsCoordinateReferenceSystem & crs