QGIS API Documentation 3.99.0-Master (d270888f95f)
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
17
18#include "qgsapplication.h"
20#include "qgsdatums.h"
22#include "qgsproject.h"
25#include "qgssettings.h"
26
27#include <QHBoxLayout>
28#include <QString>
29
30#include "moc_qgsprojectionselectionwidget.cpp"
31
32using namespace Qt::StringLiterals;
33
34#ifdef ENABLE_MODELTEST
35#include "modeltest.h"
36#endif
37
38
40StandardCoordinateReferenceSystemsModel::StandardCoordinateReferenceSystemsModel( QObject *parent )
41 : QAbstractItemModel( parent )
42 , mProjectCrs( QgsProject::instance()->crs() )
43{
44#ifdef ENABLE_MODELTEST
45 new ModelTest( this, this );
46#endif
47
48 const QgsSettings settings;
49 mDefaultCrs = QgsCoordinateReferenceSystem( settings.value( u"/projections/defaultProjectCrs"_s, Qgis::geographicCrsAuthId(), QgsSettings::App ).toString() );
50
52 mCurrentCrs.updateDefinition();
53 mLayerCrs.updateDefinition();
54 mProjectCrs.updateDefinition();
55 mDefaultCrs.updateDefinition();
56 } );
57
58 connect( QgsProject::instance(), &QgsProject::crsChanged, this, [this] {
59 mProjectCrs = QgsProject::instance()->crs();
60 } );
61}
62
63Qt::ItemFlags StandardCoordinateReferenceSystemsModel::flags( const QModelIndex &index ) const
64{
65 if ( !index.isValid() )
66 {
67 return Qt::ItemFlags();
68 }
69
70 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
71}
72
73QVariant StandardCoordinateReferenceSystemsModel::data( const QModelIndex &index, int role ) const
74{
75 const QgsProjectionSelectionWidget::CrsOption option = optionForIndex( index );
77 return QVariant();
78
79 const QgsCoordinateReferenceSystem crs = StandardCoordinateReferenceSystemsModel::crs( index );
80 switch ( role )
81 {
82 case Qt::DisplayRole:
83 case Qt::ToolTipRole:
84 switch ( option )
85 {
87 return tr( "Project CRS: %1" ).arg( mProjectCrs.userFriendlyIdentifier() );
89 return tr( "Default CRS: %1" ).arg( mDefaultCrs.userFriendlyIdentifier() );
91 return tr( "Layer CRS: %1" ).arg( mLayerCrs.userFriendlyIdentifier() );
93 return mNotSetText;
98 break;
99 }
100 break;
101
102 case RoleCrs:
103 return crs;
104
105 case RoleOption:
106 return static_cast<int>( option );
107
108 default:
109 break;
110 }
111
112 return QVariant();
113}
114
115int StandardCoordinateReferenceSystemsModel::rowCount( const QModelIndex &parent ) const
116{
117 if ( parent.isValid() )
118 return 0;
119
120 return 5;
121}
122
123int StandardCoordinateReferenceSystemsModel::columnCount( const QModelIndex & ) const
124{
125 return 1;
126}
127
128QModelIndex StandardCoordinateReferenceSystemsModel::index( int row, int column, const QModelIndex &parent ) const
129{
130 if ( row < 0 || row >= rowCount() || column != 0 || parent.isValid() )
131 return QModelIndex();
132
133 return createIndex( row, column );
134}
135
136QModelIndex StandardCoordinateReferenceSystemsModel::parent( const QModelIndex & ) const
137{
138 return QModelIndex();
139}
140
141QgsCoordinateReferenceSystem StandardCoordinateReferenceSystemsModel::crs( const QModelIndex &index ) const
142{
143 if ( !index.isValid() )
145
146 const QgsProjectionSelectionWidget::CrsOption option = optionForIndex( index );
147 switch ( option )
148 {
150 return mProjectCrs;
152 return mDefaultCrs;
154 return mCurrentCrs;
156 return mLayerCrs;
161 }
163}
164
165QgsProjectionSelectionWidget::CrsOption StandardCoordinateReferenceSystemsModel::optionForIndex( const QModelIndex &index ) const
166{
167 if ( !index.isValid() )
169
170 const int row = index.row();
171 switch ( row )
172 {
173 case 0:
175 case 1:
177 case 2:
179 case 3:
181 case 4:
183 default:
184 break;
185 }
186
188}
189
190QModelIndex StandardCoordinateReferenceSystemsModel::indexForOption( QgsProjectionSelectionWidget::CrsOption option ) const
191{
192 int row = 0;
193 switch ( option )
194 {
197 return QModelIndex();
199 row = 0;
200 break;
202 row = 1;
203 break;
205 row = 2;
206 break;
208 row = 3;
209 break;
211 row = 4;
212 break;
213 }
214
215 return index( row, 0, QModelIndex() );
216}
217
218void StandardCoordinateReferenceSystemsModel::setLayerCrs( const QgsCoordinateReferenceSystem &crs )
219{
220 mLayerCrs = crs;
221 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::LayerCrs );
222 emit dataChanged( index, index );
223}
224
225void StandardCoordinateReferenceSystemsModel::setCurrentCrs( const QgsCoordinateReferenceSystem &crs )
226{
227 mCurrentCrs = crs;
228 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::LayerCrs );
229 emit dataChanged( index, index );
230}
231
232void StandardCoordinateReferenceSystemsModel::setNotSetText( const QString &text )
233{
234 mNotSetText = text;
235 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::CrsNotSet );
236 emit dataChanged( index, index );
237}
238
239//
240// CombinedCoordinateReferenceSystemsModel
241//
242
243CombinedCoordinateReferenceSystemsModel::CombinedCoordinateReferenceSystemsModel( QObject *parent )
244 : QConcatenateTablesProxyModel( parent )
245 , mStandardModel( new StandardCoordinateReferenceSystemsModel( this ) )
246 , mRecentModel( new QgsRecentCoordinateReferenceSystemsProxyModel( this ) )
247{
248 addSourceModel( mStandardModel );
249 addSourceModel( mRecentModel );
250}
251
252void CombinedCoordinateReferenceSystemsModel::setNotSetText( const QString &text )
253{
254 mStandardModel->setNotSetText( text );
255}
256
257QString CombinedCoordinateReferenceSystemsModel::notSetText() const
258{
259 return mStandardModel->notSetText();
260}
261
262QgsCoordinateReferenceSystem CombinedCoordinateReferenceSystemsModel::currentCrs() const
263{
264 return mStandardModel->currentCrs();
265}
266
267//
268// CombinedCoordinateReferenceSystemsProxyModel
269//
270CombinedCoordinateReferenceSystemsProxyModel::CombinedCoordinateReferenceSystemsProxyModel( QObject *parent )
271 : QSortFilterProxyModel( parent )
272 , mModel( new CombinedCoordinateReferenceSystemsModel( this ) )
273{
274 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::CurrentCrs, true );
275 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::ProjectCrs, true );
276 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::DefaultCrs, true );
277
278 setSourceModel( mModel );
279 setDynamicSortFilter( true );
280}
281
282bool CombinedCoordinateReferenceSystemsProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
283{
284 const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
285
286 const QgsCoordinateReferenceSystem crs = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
287 if ( !mFilteredCrs.isEmpty() && !mFilteredCrs.contains( crs ) )
288 return false;
289
290 switch ( crs.type() )
291 {
294 break;
295
306 return false;
307 break;
308
311 return false;
312 break;
313
316 return false;
317 break;
318 }
319
320 const QVariant optionInt = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleOption );
321 if ( optionInt.isValid() )
322 {
323 if ( optionInt.toInt() > 0 )
324 {
325 const QgsProjectionSelectionWidget::CrsOption option = static_cast<QgsProjectionSelectionWidget::CrsOption>( optionInt.toInt() );
326 if ( !mVisibleOptions.testFlag( option ) )
327 return false;
328
329 // specific logic for showing/hiding options:
330 switch ( option )
331 {
333 break;
334
337 // only show these options if the crs is valid
338 return crs.isValid();
339
341 // hide invalid current CRS value option only if "not set" option is shown
342 return crs.isValid() || !mVisibleOptions.testFlag( QgsProjectionSelectionWidget::CrsNotSet );
343
347 // always shown
348 break;
349 }
350 return true;
351 }
352 }
353 else
354 {
355 // a recent crs
356 // these are only shown if they aren't duplicates of a standard item already shown in the list
357 for ( QgsProjectionSelectionWidget::CrsOption standardOption :
358 {
363 } )
364 {
365 const QModelIndexList standardItemIndex = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption, static_cast<int>( standardOption ) );
366 if ( standardItemIndex.empty() )
367 continue;
368
369 const QgsCoordinateReferenceSystem standardItemCrs = mModel->data( standardItemIndex.at( 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
370 if ( standardItemCrs == crs && filterAcceptsRow( standardItemIndex.at( 0 ).row(), QModelIndex() ) )
371 return false;
372 }
373 }
374
375 return true;
376}
377
378void CombinedCoordinateReferenceSystemsProxyModel::setLayerCrs( const QgsCoordinateReferenceSystem &crs )
379{
380 mModel->standardModel()->setLayerCrs( crs );
381 invalidateFilter();
382}
383
384void CombinedCoordinateReferenceSystemsProxyModel::setCurrentCrs( const QgsCoordinateReferenceSystem &crs )
385{
386 mModel->standardModel()->setCurrentCrs( crs );
387 invalidateFilter();
388}
389
390void CombinedCoordinateReferenceSystemsProxyModel::setFilters( QgsCoordinateReferenceSystemProxyModel::Filters filters )
391{
392 mFilters = filters;
393 invalidateFilter();
394}
395
396QgsCoordinateReferenceSystemProxyModel::Filters CombinedCoordinateReferenceSystemsProxyModel::filters() const
397{
398 return mFilters;
399}
400
401void CombinedCoordinateReferenceSystemsProxyModel::setFilteredCrs( const QList<QgsCoordinateReferenceSystem> &crses )
402{
403 mFilteredCrs = crses;
404 invalidateFilter();
405}
406
407void CombinedCoordinateReferenceSystemsProxyModel::setOption( QgsProjectionSelectionWidget::CrsOption option, bool enabled )
408{
409 mVisibleOptions.setFlag( option, enabled );
410 invalidateFilter();
411}
412
414
415
417 : QWidget( parent )
418 , mDialogTitle( tr( "Coordinate Reference System Selector" ) )
419{
420 mCrsComboBox = new QgsHighlightableComboBox( this );
421 mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
422
423 mModel = new CombinedCoordinateReferenceSystemsProxyModel( this );
424 mModel->setFilters( filters );
425 mCrsComboBox->setModel( mModel );
426
427 const int labelMargin = static_cast<int>( std::round( mCrsComboBox->fontMetrics().horizontalAdvance( 'X' ) ) );
428 QHBoxLayout *layout = new QHBoxLayout();
429 layout->setContentsMargins( 0, 0, 0, 0 );
430 layout->setSpacing( 0 );
431 setLayout( layout );
432
433 layout->addWidget( mCrsComboBox, 1 );
434
435 // bit of fiddlyness here -- we want the initial spacing to only be visible
436 // when the warning label is shown, so it's embedded inside mWarningLabel
437 // instead of outside it
438 mWarningLabelContainer = new QWidget();
439 QHBoxLayout *warningLayout = new QHBoxLayout();
440 warningLayout->setContentsMargins( 0, 0, 0, 0 );
441 mWarningLabel = new QLabel();
442 const QIcon icon = QgsApplication::getThemeIcon( u"mIconWarning.svg"_s );
443 const int size = static_cast<int>( std::max( 24.0, mCrsComboBox->minimumSize().height() * 0.5 ) );
444 mWarningLabel->setPixmap( icon.pixmap( icon.actualSize( QSize( size, size ) ) ) );
445 warningLayout->insertSpacing( 0, labelMargin / 2 );
446 warningLayout->insertWidget( 1, mWarningLabel );
447 mWarningLabelContainer->setLayout( warningLayout );
448 layout->addWidget( mWarningLabelContainer );
449 mWarningLabelContainer->hide();
450
451 layout->addSpacing( labelMargin / 2 );
452
453 mButton = new QToolButton( this );
454 mButton->setIcon( QgsApplication::getThemeIcon( u"mActionSetProjection.svg"_s ) );
455 mButton->setToolTip( tr( "Select CRS" ) );
456 layout->addWidget( mButton );
457
458 setFocusPolicy( Qt::StrongFocus );
459 setFocusProxy( mButton );
460 setAcceptDrops( true );
461
462 connect( mButton, &QToolButton::clicked, this, &QgsProjectionSelectionWidget::selectCrs );
463 connect( mCrsComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsProjectionSelectionWidget::comboIndexChanged );
464}
465
467{
468 const int idx = mCrsComboBox->currentIndex();
469 if ( idx >= 0 && idx < mModel->rowCount() )
470 return mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
471 else
473}
474
476{
477 switch ( option )
478 {
483 {
484 mModel->setOption( option, visible );
485 updateTooltip();
486 return;
487 }
489 //recently used CRS option cannot be readded
490 return;
492 {
493 mModel->setOption( CrsNotSet, visible );
494
495 if ( !visible )
496 {
498 }
499 else
500 {
501 if ( !mModel->combinedModel()->currentCrs().isValid() )
502 whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
503 }
504 updateTooltip();
505
506 return;
507 }
508 case Invalid:
509 return;
510 }
511}
512
514{
515 mModel->combinedModel()->setNotSetText( text );
516}
517
519{
520 mMessage = text;
521}
522
524{
525 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption, static_cast<int>( option ) );
526 return !matches.empty();
527}
528
530{
532 const QList<QgsCoordinateReferenceSystem> filteredCrses = mModel->filteredCrs();
533
534 QSet<QString> ogcFilter;
535 ogcFilter.reserve( filteredCrses.size() );
536 for ( const QgsCoordinateReferenceSystem &crs : std::as_const( filteredCrses ) )
537 {
538 ogcFilter << crs.authid();
539 }
540
541 if ( panel && panel->dockMode() )
542 {
543 mActivePanel = new QgsCrsSelectionWidget( this, mModel->filters() );
544 if ( !ogcFilter.isEmpty() )
545 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
546 if ( !mMessage.isEmpty() )
547 mActivePanel->setMessage( mMessage );
548 mActivePanel->setCrs( crs() );
549
550 if ( !mModel->combinedModel()->notSetText().isEmpty() )
551 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
552
553 mActivePanel->setPanelTitle( mDialogTitle );
554
556 {
557 mActivePanel->setShowNoCrs( true );
558 }
559
560 connect( mActivePanel, &QgsCrsSelectionWidget::crsChanged, this, [this] {
561 if ( mIgnorePanelSignals )
562 return;
563
564 if ( !mActivePanel->hasValidSelection() )
565 return;
566
567 mCrsComboBox->blockSignals( true );
568 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
569 mCrsComboBox->blockSignals( false );
570 const QgsCoordinateReferenceSystem crs = mActivePanel->crs();
571
572 mIgnorePanelSignals++;
573 setCrs( crs );
574 mIgnorePanelSignals--;
575
576 emit crsChanged( crs );
577 } );
578 panel->openPanel( mActivePanel );
579 }
580 else
581 {
582 QgsProjectionSelectionDialog dlg( this, QgsGuiUtils::ModalDialogFlags, mModel->filters() );
583 if ( !mMessage.isEmpty() )
584 dlg.setMessage( mMessage );
585 if ( !ogcFilter.isEmpty() )
586 dlg.setOgcWmsCrsFilter( ogcFilter );
587 dlg.setCrs( crs() );
588 dlg.setWindowTitle( mDialogTitle );
589
590 if ( !mModel->combinedModel()->notSetText().isEmpty() )
591 dlg.setNotSetText( mModel->combinedModel()->notSetText() );
592
594 {
595 dlg.setShowNoProjection( true );
596 }
598
599 if ( dlg.exec() )
600 {
601 mCrsComboBox->blockSignals( true );
602 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
603 mCrsComboBox->blockSignals( false );
605 // setCrs will emit crsChanged for us
606 setCrs( crs );
607 }
608 else
609 {
610 QApplication::restoreOverrideCursor();
611 }
612 }
613}
614
616{
617 if ( !( event->possibleActions() & Qt::CopyAction ) )
618 {
619 event->ignore();
620 return;
621 }
622
623 if ( mapLayerFromMimeData( event->mimeData() ) )
624 {
625 // dragged an acceptable layer, phew
626 event->setDropAction( Qt::CopyAction );
627 event->accept();
628 mCrsComboBox->setHighlighted( true );
629 update();
630 }
631 else
632 {
633 event->ignore();
634 }
635}
636
638{
639 if ( mCrsComboBox->isHighlighted() )
640 {
641 event->accept();
642 mCrsComboBox->setHighlighted( false );
643 update();
644 }
645 else
646 {
647 event->ignore();
648 }
649}
650
652{
653 if ( !( event->possibleActions() & Qt::CopyAction ) )
654 {
655 event->ignore();
656 return;
657 }
658
659 if ( QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
660 {
661 // dropped a map layer
662 setFocus( Qt::MouseFocusReason );
663 event->setDropAction( Qt::CopyAction );
664 event->accept();
665
666 if ( layer->crs().isValid() )
667 setCrs( layer->crs() );
668 }
669 else
670 {
671 event->ignore();
672 }
673 mCrsComboBox->setHighlighted( false );
674 update();
675}
676
678{
679 return mSourceEnsemble;
680}
681
683{
684 mDialogTitle = title;
685}
686
688{
689 return mDialogTitle;
690}
691
692void QgsProjectionSelectionWidget::setFilter( const QList<QgsCoordinateReferenceSystem> &crses )
693{
694 mModel->setFilteredCrs( crses );
695}
696
701
703{
704 mModel->setFilters( filters );
705 if ( mActivePanel )
706 mActivePanel->setFilters( filters );
707}
708
710{
711 if ( mSourceEnsemble == ensemble )
712 return;
713
714 mSourceEnsemble = ensemble;
715 updateWarning();
716}
717
719{
720 return mShowAccuracyWarnings;
721}
722
724{
725 mShowAccuracyWarnings = show;
726 if ( !mShowAccuracyWarnings )
727 mWarningLabelContainer->hide();
728 else
729 updateWarning();
730}
731
732void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
733{
734 if ( idx >= 0 && idx < mModel->rowCount() )
735 {
736 const QgsCoordinateReferenceSystem crs = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
737 const QVariant optionData = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption );
738 if ( !optionData.isValid() || static_cast<CrsOption>( optionData.toInt() ) != QgsProjectionSelectionWidget::CrsNotSet )
739 {
740 // RoleOption is only available for items from the standard coordinate reference system model, but we
741 // are using a combined model which also has items from QgsRecentCoordinateReferenceSystemsModel
742 emit crsChanged( crs );
743 }
744 else
745 {
746 emit cleared();
747 emit crsChanged( QgsCoordinateReferenceSystem() );
748 }
749 }
750
751 updateTooltip();
752}
753
754void QgsProjectionSelectionWidget::updateWarning()
755{
756 if ( !mShowAccuracyWarnings )
757 {
758 if ( mWarningLabelContainer->isVisible() )
759 mWarningLabelContainer->hide();
760 return;
761 }
762
763 try
764 {
765 const double crsAccuracyWarningThreshold = QgsSettings().value( u"/projections/crsAccuracyWarningThreshold"_s, 0.0, QgsSettings::App ).toDouble();
766
767 const QgsDatumEnsemble ensemble = crs().datumEnsemble();
768 if ( !ensemble.isValid() || ensemble.name() == mSourceEnsemble || ( ensemble.accuracy() > 0 && ensemble.accuracy() < crsAccuracyWarningThreshold ) )
769 {
770 mWarningLabelContainer->hide();
771 }
772 else
773 {
774 mWarningLabelContainer->show();
775
776 QString warning = u"<p>"_s;
777
778 QString id;
779 if ( !ensemble.code().isEmpty() )
780 id = u"<i>%1</i> (%2:%3)"_s.arg( ensemble.name(), ensemble.authority(), ensemble.code() );
781 else
782 id = u"<i>%1</i>”"_s.arg( ensemble.name() );
783
784 if ( ensemble.accuracy() > 0 )
785 {
786 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() );
787 }
788 else
789 {
790 warning = tr( "The selected CRS is based on %1, which has a limited accuracy." ).arg( id );
791 }
792 warning += u"</p><p>"_s + tr( "Use an alternative CRS if accurate positioning is required." ) + u"</p>"_s;
793
794 const QList<QgsDatumEnsembleMember> members = ensemble.members();
795 if ( !members.isEmpty() )
796 {
797 warning += u"<p>"_s + tr( "%1 consists of the datums:" ).arg( ensemble.name() ) + u"</p><ul>"_s;
798
799 for ( const QgsDatumEnsembleMember &member : members )
800 {
801 if ( !member.code().isEmpty() )
802 id = u"%1 (%2:%3)"_s.arg( member.name(), member.authority(), member.code() );
803 else
804 id = member.name();
805 warning += u"<li>%1</li>"_s.arg( id );
806 }
807
808 warning += "</ul>"_L1;
809 }
810
811 mWarningLabel->setToolTip( warning );
812 }
813 }
814 catch ( QgsNotSupportedException & )
815 {
816 mWarningLabelContainer->hide();
817 }
818}
819
821{
822 const QgsCoordinateReferenceSystem prevCrs = mModel->combinedModel()->currentCrs();
823 mModel->setCurrentCrs( crs );
824
825 if ( crs.isValid() )
826 {
828 mCrsComboBox->blockSignals( true );
829 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
830 mCrsComboBox->blockSignals( false );
831 }
832 else
833 {
834 const int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet, StandardCoordinateReferenceSystemsModel::Role::RoleOption );
835 if ( crsNotSetIndex >= 0 )
836 {
837 mCrsComboBox->blockSignals( true );
838 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
839 mCrsComboBox->blockSignals( false );
840 }
841 }
842 if ( mActivePanel && !mIgnorePanelSignals )
843 {
844 mIgnorePanelSignals++;
845 mActivePanel->setCrs( crs );
846 mIgnorePanelSignals--;
847 }
848 if ( prevCrs != crs )
849 {
850 emit crsChanged( crs );
851 }
852 updateTooltip();
853}
854
856{
857 mModel->setLayerCrs( crs );
858}
859
861{
862 if ( crs.isValid() )
863 return crs.userFriendlyIdentifier();
864 else
865 return tr( "invalid projection" );
866}
867
868void QgsProjectionSelectionWidget::updateTooltip()
869{
871 if ( c.isValid() )
872 setToolTip( c.toWkt( Qgis::CrsWktVariant::Preferred, true ) );
873 else
874 setToolTip( QString() );
875 updateWarning();
876}
877
878QgsMapLayer *QgsProjectionSelectionWidget::mapLayerFromMimeData( const QMimeData *data ) const
879{
881 for ( const QgsMimeDataUtils::Uri &u : uriList )
882 {
883 // is this uri from the current project?
884 if ( QgsMapLayer *layer = u.mapLayer() )
885 {
886 return layer;
887 }
888 }
889 return nullptr;
890}
@ 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
static QString geographicCrsAuthId()
Geographic coordinate system auth:id string for a default geographic CRS (EPSG:4326).
Definition qgis.h:6625
@ 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...
@ 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.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
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.
QString code() const
Identification code, e.g.
Definition qgsdatums.h:124
QString authority() const
Authority name, e.g.
Definition qgsdatums.h:119
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:104
QList< QgsDatumEnsembleMember > members() const
Contains a list of members of the ensemble.
Definition qgsdatums.h:139
QString name() const
Display name of datum ensemble.
Definition qgsdatums.h:109
double accuracy() const
Positional accuracy (in meters).
Definition qgsdatums.h:114
A QComboBox subclass with the ability to "highlight" the edges of the widget.
Base class for all map layer types.
Definition qgsmaplayer.h:83
QList< QgsMimeDataUtils::Uri > UriList
static UriList decodeUriList(const QMimeData *data)
Base class for any widget that can be shown as an 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 ...
bool dockMode() const
Returns the dock mode state.
static QgsPanelWidget * findParentPanel(QWidget *widget)
Traces through the parents of a widget to find if it is contained within a QgsPanelWidget widget.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
Definition qgsproject.h:112
static QgsProject * instance()
Returns the QgsProject singleton instance.
void crsChanged()
Emitted when the crs() of the project has changed.
QgsCoordinateReferenceSystem crs
Definition qgsproject.h:118
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.
Stores settings for use within QGIS.
Definition qgssettings.h:68
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:7489
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:6804