QGIS API Documentation 3.41.0-Master (fda2aa46e9a)
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 {
48 mCurrentCrs.updateDefinition();
49 mLayerCrs.updateDefinition();
50 mProjectCrs.updateDefinition();
51 mDefaultCrs.updateDefinition();
52 } );
53}
54
55Qt::ItemFlags StandardCoordinateReferenceSystemsModel::flags( const QModelIndex &index ) const
56{
57 if ( !index.isValid() )
58 {
59 return Qt::ItemFlags();
60 }
61
62 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
63}
64
65QVariant StandardCoordinateReferenceSystemsModel::data( const QModelIndex &index, int role ) const
66{
67 const QgsProjectionSelectionWidget::CrsOption option = optionForIndex( index );
69 return QVariant();
70
71 const QgsCoordinateReferenceSystem crs = StandardCoordinateReferenceSystemsModel::crs( index );
72 switch ( role )
73 {
74 case Qt::DisplayRole:
75 case Qt::ToolTipRole:
76 switch ( option )
77 {
79 return tr( "Project CRS: %1" ).arg( crs.userFriendlyIdentifier() );
81 return tr( "Default CRS: %1" ).arg( crs.userFriendlyIdentifier() );
83 return tr( "Layer CRS: %1" ).arg( crs.userFriendlyIdentifier() );
85 return mNotSetText;
90 break;
91 }
92 break;
93
94 case RoleCrs:
95 return crs;
96
97 case RoleOption:
98 return static_cast< int >( option );
99
100 default:
101 break;
102 }
103
104 return QVariant();
105}
106
107int StandardCoordinateReferenceSystemsModel::rowCount( const QModelIndex &parent ) const
108{
109 if ( parent.isValid() )
110 return 0;
111
112 return 5;
113}
114
115int StandardCoordinateReferenceSystemsModel::columnCount( const QModelIndex & ) const
116{
117 return 1;
118}
119
120QModelIndex StandardCoordinateReferenceSystemsModel::index( int row, int column, const QModelIndex &parent ) const
121{
122 if ( row < 0 || row >= rowCount() || column != 0 || parent.isValid() )
123 return QModelIndex();
124
125 return createIndex( row, column );
126}
127
128QModelIndex StandardCoordinateReferenceSystemsModel::parent( const QModelIndex & ) const
129{
130 return QModelIndex();
131}
132
133QgsCoordinateReferenceSystem StandardCoordinateReferenceSystemsModel::crs( const QModelIndex &index ) const
134{
135 if ( !index.isValid() )
137
138 const QgsProjectionSelectionWidget::CrsOption option = optionForIndex( index );
139 switch ( option )
140 {
142 return mProjectCrs;
144 return mDefaultCrs;
146 return mCurrentCrs;
148 return mLayerCrs;
153 }
155}
156
157QgsProjectionSelectionWidget::CrsOption StandardCoordinateReferenceSystemsModel::optionForIndex( const QModelIndex &index ) const
158{
159 if ( !index.isValid() )
161
162 const int row = index.row();
163 switch ( row )
164 {
165 case 0:
167 case 1:
169 case 2:
171 case 3:
173 case 4:
175 default:
176 break;
177 }
178
180}
181
182QModelIndex StandardCoordinateReferenceSystemsModel::indexForOption( QgsProjectionSelectionWidget::CrsOption option ) const
183{
184 int row = 0;
185 switch ( option )
186 {
189 return QModelIndex();
191 row = 0;
192 break;
194 row = 1;
195 break;
197 row = 2;
198 break;
200 row = 3;
201 break;
203 row = 4;
204 break;
205 }
206
207 return index( row, 0, QModelIndex() );
208}
209
210void StandardCoordinateReferenceSystemsModel::setLayerCrs( const QgsCoordinateReferenceSystem &crs )
211{
212 mLayerCrs = crs;
213 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::LayerCrs );
214 emit dataChanged( index, index );
215}
216
217void StandardCoordinateReferenceSystemsModel::setCurrentCrs( const QgsCoordinateReferenceSystem &crs )
218{
219 mCurrentCrs = crs;
220 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::LayerCrs );
221 emit dataChanged( index, index );
222}
223
224void StandardCoordinateReferenceSystemsModel::setNotSetText( const QString &text )
225{
226 mNotSetText = text;
227 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::CrsNotSet );
228 emit dataChanged( index, index );
229}
230
231//
232// CombinedCoordinateReferenceSystemsModel
233//
234
235CombinedCoordinateReferenceSystemsModel::CombinedCoordinateReferenceSystemsModel( QObject *parent )
236 : QConcatenateTablesProxyModel( parent )
237 , mStandardModel( new StandardCoordinateReferenceSystemsModel( this ) )
238 , mRecentModel( new QgsRecentCoordinateReferenceSystemsProxyModel( this ) )
239{
240 addSourceModel( mStandardModel );
241 addSourceModel( mRecentModel );
242}
243
244void CombinedCoordinateReferenceSystemsModel::setNotSetText( const QString &text )
245{
246 mStandardModel->setNotSetText( text );
247}
248
249QString CombinedCoordinateReferenceSystemsModel::notSetText() const
250{
251 return mStandardModel->notSetText();
252}
253
254QgsCoordinateReferenceSystem CombinedCoordinateReferenceSystemsModel::currentCrs() const
255{
256 return mStandardModel->currentCrs();
257}
258
259//
260// CombinedCoordinateReferenceSystemsProxyModel
261//
262CombinedCoordinateReferenceSystemsProxyModel::CombinedCoordinateReferenceSystemsProxyModel( QObject *parent )
263 : QSortFilterProxyModel( parent )
264 , mModel( new CombinedCoordinateReferenceSystemsModel( this ) )
265{
266 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::CurrentCrs, true );
267 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::ProjectCrs, true );
268 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::DefaultCrs, true );
269
270 setSourceModel( mModel );
271 setDynamicSortFilter( true );
272}
273
274bool CombinedCoordinateReferenceSystemsProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
275{
276 const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
277
278 const QgsCoordinateReferenceSystem crs = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleCrs ).value< QgsCoordinateReferenceSystem >();
279 if ( !mFilteredCrs.isEmpty() && !mFilteredCrs.contains( crs ) )
280 return false;
281
282 switch ( crs.type() )
283 {
286 break;
287
298 return false;
299 break;
300
303 return false;
304 break;
305
308 return false;
309 break;
310 }
311
312 const QVariant optionInt = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleOption );
313 if ( optionInt.isValid() )
314 {
315 if ( optionInt.toInt() > 0 )
316 {
317 const QgsProjectionSelectionWidget::CrsOption option = static_cast< QgsProjectionSelectionWidget::CrsOption >( optionInt.toInt() );
318 if ( !mVisibleOptions.testFlag( option ) )
319 return false;
320
321 // specific logic for showing/hiding options:
322 switch ( option )
323 {
325 break;
326
329 // only show these options if the crs is valid
330 return crs.isValid();
331
333 // hide invalid current CRS value option only if "not set" option is shown
334 return crs.isValid() || !mVisibleOptions.testFlag( QgsProjectionSelectionWidget::CrsNotSet );
335
339 // always shown
340 break;
341 }
342 return true;
343 }
344 }
345 else
346 {
347 // a recent crs
348 // these are only shown if they aren't duplicates of a standard item already shown in the list
349 for ( QgsProjectionSelectionWidget::CrsOption standardOption :
350 {
355 } )
356 {
357 const QModelIndexList standardItemIndex = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption, static_cast< int >( standardOption ) );
358 if ( standardItemIndex.empty() )
359 continue;
360
361 const QgsCoordinateReferenceSystem standardItemCrs = mModel->data( standardItemIndex.at( 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value< QgsCoordinateReferenceSystem >();
362 if ( standardItemCrs == crs && filterAcceptsRow( standardItemIndex.at( 0 ).row(), QModelIndex() ) )
363 return false;
364 }
365 }
366
367 return true;
368}
369
370void CombinedCoordinateReferenceSystemsProxyModel::setLayerCrs( const QgsCoordinateReferenceSystem &crs )
371{
372 mModel->standardModel()->setLayerCrs( crs );
373 invalidateFilter();
374}
375
376void CombinedCoordinateReferenceSystemsProxyModel::setCurrentCrs( const QgsCoordinateReferenceSystem &crs )
377{
378 mModel->standardModel()->setCurrentCrs( crs );
379 invalidateFilter();
380}
381
382void CombinedCoordinateReferenceSystemsProxyModel::setFilters( QgsCoordinateReferenceSystemProxyModel::Filters filters )
383{
384 mFilters = filters;
385 invalidateFilter();
386}
387
388QgsCoordinateReferenceSystemProxyModel::Filters CombinedCoordinateReferenceSystemsProxyModel::filters() const
389{
390 return mFilters;
391}
392
393void CombinedCoordinateReferenceSystemsProxyModel::setFilteredCrs( const QList<QgsCoordinateReferenceSystem> &crses )
394{
395 mFilteredCrs = crses;
396 invalidateFilter();
397}
398
399void CombinedCoordinateReferenceSystemsProxyModel::setOption( QgsProjectionSelectionWidget::CrsOption option, bool enabled )
400{
401 mVisibleOptions.setFlag( option, enabled );
402 invalidateFilter();
403}
404
406
407
410 : QWidget( parent )
411 , mDialogTitle( tr( "Coordinate Reference System Selector" ) )
412{
413 mCrsComboBox = new QgsHighlightableComboBox( this );
414 mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
415
416 mModel = new CombinedCoordinateReferenceSystemsProxyModel( this );
417 mModel->setFilters( filters );
418 mCrsComboBox->setModel( mModel );
419
420 const int labelMargin = static_cast< int >( std::round( mCrsComboBox->fontMetrics().horizontalAdvance( 'X' ) ) );
421 QHBoxLayout *layout = new QHBoxLayout();
422 layout->setContentsMargins( 0, 0, 0, 0 );
423 layout->setSpacing( 0 );
424 setLayout( layout );
425
426 layout->addWidget( mCrsComboBox, 1 );
427
428 // bit of fiddlyness here -- we want the initial spacing to only be visible
429 // when the warning label is shown, so it's embedded inside mWarningLabel
430 // instead of outside it
431 mWarningLabelContainer = new QWidget();
432 QHBoxLayout *warningLayout = new QHBoxLayout();
433 warningLayout->setContentsMargins( 0, 0, 0, 0 );
434 mWarningLabel = new QLabel();
435 const QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "mIconWarning.svg" ) );
436 const int size = static_cast< int >( std::max( 24.0, mCrsComboBox->minimumSize().height() * 0.5 ) );
437 mWarningLabel->setPixmap( icon.pixmap( icon.actualSize( QSize( size, size ) ) ) );
438 warningLayout->insertSpacing( 0, labelMargin / 2 );
439 warningLayout->insertWidget( 1, mWarningLabel );
440 mWarningLabelContainer->setLayout( warningLayout );
441 layout->addWidget( mWarningLabelContainer );
442 mWarningLabelContainer->hide();
443
444 layout->addSpacing( labelMargin / 2 );
445
446 mButton = new QToolButton( this );
447 mButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionSetProjection.svg" ) ) );
448 mButton->setToolTip( tr( "Select CRS" ) );
449 layout->addWidget( mButton );
450
451 setFocusPolicy( Qt::StrongFocus );
452 setFocusProxy( mButton );
453 setAcceptDrops( true );
454
455 connect( mButton, &QToolButton::clicked, this, &QgsProjectionSelectionWidget::selectCrs );
456 connect( mCrsComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsProjectionSelectionWidget::comboIndexChanged );
457}
458
460{
461 const int idx = mCrsComboBox->currentIndex();
462 if ( idx >= 0 && idx < mModel->rowCount() )
463 return mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value< QgsCoordinateReferenceSystem >();
464 else
466}
467
469{
470 switch ( option )
471 {
476 {
477 mModel->setOption( option, visible );
478 updateTooltip();
479 return;
480 }
482 //recently used CRS option cannot be readded
483 return;
485 {
486 mModel->setOption( CrsNotSet, visible );
487
488 if ( !visible )
489 {
491 }
492 else
493 {
494 if ( !mModel->combinedModel()->currentCrs().isValid() )
495 whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
496 }
497 updateTooltip();
498
499 return;
500 }
501 case Invalid:
502 return;
503 }
504}
505
507{
508 mModel->combinedModel()->setNotSetText( text );
509}
510
512{
513 mMessage = text;
514}
515
517{
518 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption, static_cast< int >( option ) );
519 return !matches.empty();
520}
521
523{
525 const QList< QgsCoordinateReferenceSystem > filteredCrses = mModel->filteredCrs();
526
527 QSet< QString > ogcFilter;
528 ogcFilter.reserve( filteredCrses.size( ) );
529 for ( const QgsCoordinateReferenceSystem &crs : std::as_const( filteredCrses ) )
530 {
531 ogcFilter << crs.authid();
532 }
533
534 if ( panel && panel->dockMode() )
535 {
536 mActivePanel = new QgsCrsSelectionWidget( this, mModel->filters() );
537 if ( !ogcFilter.isEmpty() )
538 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
539 if ( !mMessage.isEmpty() )
540 mActivePanel->setMessage( mMessage );
541 mActivePanel->setCrs( crs() );
542
543 if ( !mModel->combinedModel()->notSetText().isEmpty() )
544 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
545
546 mActivePanel->setPanelTitle( mDialogTitle );
547
549 {
550 mActivePanel->setShowNoCrs( true );
551 }
552
553 connect( mActivePanel, &QgsCrsSelectionWidget::crsChanged, this, [ this ]
554 {
555 if ( mIgnorePanelSignals )
556 return;
557
558 if ( !mActivePanel->hasValidSelection() )
559 return;
560
561 mCrsComboBox->blockSignals( true );
562 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
563 mCrsComboBox->blockSignals( false );
564 const QgsCoordinateReferenceSystem crs = mActivePanel->crs();
565
566 mIgnorePanelSignals++;
567 setCrs( crs );
568 mIgnorePanelSignals--;
569
570 emit crsChanged( crs );
571 } );
572 panel->openPanel( mActivePanel );
573 }
574 else
575 {
576 QgsProjectionSelectionDialog dlg( this, QgsGuiUtils::ModalDialogFlags, mModel->filters() );
577 if ( !mMessage.isEmpty() )
578 dlg.setMessage( mMessage );
579 if ( !ogcFilter.isEmpty() )
580 dlg.setOgcWmsCrsFilter( ogcFilter );
581 dlg.setCrs( crs() );
582 dlg.setWindowTitle( mDialogTitle );
583
584 if ( !mModel->combinedModel()->notSetText().isEmpty() )
585 dlg.setNotSetText( mModel->combinedModel()->notSetText() );
586
588 {
589 dlg.setShowNoProjection( true );
590 }
592
593 if ( dlg.exec() )
594 {
595 mCrsComboBox->blockSignals( true );
596 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
597 mCrsComboBox->blockSignals( false );
599 // setCrs will emit crsChanged for us
600 setCrs( crs );
601 }
602 else
603 {
604 QApplication::restoreOverrideCursor();
605 }
606 }
607}
608
610{
611 if ( !( event->possibleActions() & Qt::CopyAction ) )
612 {
613 event->ignore();
614 return;
615 }
616
617 if ( mapLayerFromMimeData( event->mimeData() ) )
618 {
619 // dragged an acceptable layer, phew
620 event->setDropAction( Qt::CopyAction );
621 event->accept();
622 mCrsComboBox->setHighlighted( true );
623 update();
624 }
625 else
626 {
627 event->ignore();
628 }
629}
630
632{
633 if ( mCrsComboBox->isHighlighted() )
634 {
635 event->accept();
636 mCrsComboBox->setHighlighted( false );
637 update();
638 }
639 else
640 {
641 event->ignore();
642 }
643}
644
646{
647 if ( !( event->possibleActions() & Qt::CopyAction ) )
648 {
649 event->ignore();
650 return;
651 }
652
653 if ( QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
654 {
655 // dropped a map layer
656 setFocus( Qt::MouseFocusReason );
657 event->setDropAction( Qt::CopyAction );
658 event->accept();
659
660 if ( layer->crs().isValid() )
661 setCrs( layer->crs() );
662 }
663 else
664 {
665 event->ignore();
666 }
667 mCrsComboBox->setHighlighted( false );
668 update();
669}
670
672{
673 return mSourceEnsemble;
674}
675
677{
678 mDialogTitle = title;
679}
680
682{
683 return mDialogTitle;
684}
685
686void QgsProjectionSelectionWidget::setFilter( const QList<QgsCoordinateReferenceSystem> &crses )
687{
688 mModel->setFilteredCrs( crses );
689}
690
695
697{
698 mModel->setFilters( filters );
699 if ( mActivePanel )
700 mActivePanel->setFilters( filters );
701}
702
704{
705 if ( mSourceEnsemble == ensemble )
706 return;
707
708 mSourceEnsemble = ensemble;
709 updateWarning();
710}
711
713{
714 return mShowAccuracyWarnings;
715}
716
718{
719 mShowAccuracyWarnings = show;
720 if ( !mShowAccuracyWarnings )
721 mWarningLabelContainer->hide();
722 else
723 updateWarning();
724}
725
726void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
727{
728 if ( idx >= 0 && idx < mModel->rowCount() )
729 {
730 const QgsCoordinateReferenceSystem crs = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value< QgsCoordinateReferenceSystem >();
731 const QVariant optionData = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption );
732 if ( !optionData.isValid() || static_cast< CrsOption >( optionData.toInt() ) != QgsProjectionSelectionWidget::CrsNotSet )
733 {
734 // RoleOption is only available for items from the standard coordinate reference system model, but we
735 // are using a combined model which also has items from QgsRecentCoordinateReferenceSystemsModel
736 emit crsChanged( crs );
737 }
738 else
739 {
740 emit cleared();
742 }
743 }
744
745 updateTooltip();
746}
747
748void QgsProjectionSelectionWidget::updateWarning()
749{
750 if ( !mShowAccuracyWarnings )
751 {
752 if ( mWarningLabelContainer->isVisible() )
753 mWarningLabelContainer->hide();
754 return;
755 }
756
757 try
758 {
759 const double crsAccuracyWarningThreshold = QgsSettings().value( QStringLiteral( "/projections/crsAccuracyWarningThreshold" ), 0.0, QgsSettings::App ).toDouble();
760
761 const QgsDatumEnsemble ensemble = crs().datumEnsemble();
762 if ( !ensemble.isValid() || ensemble.name() == mSourceEnsemble || ( ensemble.accuracy() > 0 && ensemble.accuracy() < crsAccuracyWarningThreshold ) )
763 {
764 mWarningLabelContainer->hide();
765 }
766 else
767 {
768 mWarningLabelContainer->show();
769
770 QString warning = QStringLiteral( "<p>" );
771
772 QString id;
773 if ( !ensemble.code().isEmpty() )
774 id = QStringLiteral( "<i>%1</i> (%2:%3)" ).arg( ensemble.name(), ensemble.authority(), ensemble.code() );
775 else
776 id = QStringLiteral( "<i>%</i>”" ).arg( ensemble.name() );
777
778 if ( ensemble.accuracy() > 0 )
779 {
780 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() );
781 }
782 else
783 {
784 warning = tr( "The selected CRS is based on %1, which has a limited accuracy." ).arg( id );
785 }
786 warning += QStringLiteral( "</p><p>" ) + tr( "Use an alternative CRS if accurate positioning is required." ) + QStringLiteral( "</p>" );
787
788 const QList< QgsDatumEnsembleMember > members = ensemble.members();
789 if ( !members.isEmpty() )
790 {
791 warning += QStringLiteral( "<p>" ) + tr( "%1 consists of the datums:" ).arg( ensemble.name() ) + QStringLiteral( "</p><ul>" );
792
793 for ( const QgsDatumEnsembleMember &member : members )
794 {
795 if ( !member.code().isEmpty() )
796 id = QStringLiteral( "%1 (%2:%3)" ).arg( member.name(), member.authority(), member.code() );
797 else
798 id = member.name();
799 warning += QStringLiteral( "<li>%1</li>" ).arg( id );
800 }
801
802 warning += QLatin1String( "</ul>" );
803 }
804
805 mWarningLabel->setToolTip( warning );
806 }
807 }
808 catch ( QgsNotSupportedException & )
809 {
810 mWarningLabelContainer->hide();
811 }
812}
813
815{
816 const QgsCoordinateReferenceSystem prevCrs = mModel->combinedModel()->currentCrs();
817 mModel->setCurrentCrs( crs );
818
819 if ( crs.isValid() )
820 {
822 mCrsComboBox->blockSignals( true );
823 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
824 mCrsComboBox->blockSignals( false );
825 }
826 else
827 {
828 const int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet, StandardCoordinateReferenceSystemsModel::Role::RoleOption );
829 if ( crsNotSetIndex >= 0 )
830 {
831 mCrsComboBox->blockSignals( true );
832 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
833 mCrsComboBox->blockSignals( false );
834 }
835 }
836 if ( mActivePanel && !mIgnorePanelSignals )
837 {
838 mIgnorePanelSignals++;
839 mActivePanel->setCrs( crs );
840 mIgnorePanelSignals--;
841 }
842 if ( prevCrs != crs )
843 {
844 emit crsChanged( crs );
845 }
846 updateTooltip();
847}
848
850{
851 mModel->setLayerCrs( crs );
852}
853
855{
856 if ( crs.isValid() )
858 else
859 return tr( "invalid projection" );
860}
861
862void QgsProjectionSelectionWidget::updateTooltip()
863{
865 if ( c.isValid() )
866 setToolTip( c.toWkt( Qgis::CrsWktVariant::Preferred, true ) );
867 else
868 setToolTip( QString() );
869 updateWarning();
870}
871
872QgsMapLayer *QgsProjectionSelectionWidget::mapLayerFromMimeData( const QMimeData *data ) const
873{
875 for ( const QgsMimeDataUtils::Uri &u : uriList )
876 {
877 // is this uri from the current project?
878 if ( QgsMapLayer *layer = u.mapLayer() )
879 {
880 return layer;
881 }
882 }
883 return nullptr;
884}
@ 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:6571
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:5821
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
Definition qgis.h:6406
const QgsCoordinateReferenceSystem & crs