QGIS API Documentation 4.3.0-Master (bf28115e945)
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
6 Email : denis.rouzaud@gmail.com
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] { mProjectCrs = QgsProject::instance()->crs(); } );
59}
60
61Qt::ItemFlags StandardCoordinateReferenceSystemsModel::flags( const QModelIndex &index ) const
62{
63 if ( !index.isValid() )
64 {
65 return Qt::ItemFlags();
66 }
67
68 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
69}
70
71QVariant StandardCoordinateReferenceSystemsModel::data( const QModelIndex &index, int role ) const
72{
73 const QgsProjectionSelectionWidget::CrsOption option = optionForIndex( index );
75 return QVariant();
76
77 const QgsCoordinateReferenceSystem crs = StandardCoordinateReferenceSystemsModel::crs( index );
78 switch ( role )
79 {
80 case Qt::DisplayRole:
81 case Qt::ToolTipRole:
82 switch ( option )
83 {
85 return tr( "Project CRS: %1" ).arg( mProjectCrs.userFriendlyIdentifier() );
87 return tr( "Default CRS: %1" ).arg( mDefaultCrs.userFriendlyIdentifier() );
89 return tr( "Layer CRS: %1" ).arg( mLayerCrs.userFriendlyIdentifier() );
91 return mNotSetText;
96 break;
97 }
98 break;
99
100 case RoleCrs:
101 return crs;
102
103 case RoleOption:
104 return static_cast<int>( option );
105
106 default:
107 break;
108 }
109
110 return QVariant();
111}
112
113int StandardCoordinateReferenceSystemsModel::rowCount( const QModelIndex &parent ) const
114{
115 if ( parent.isValid() )
116 return 0;
117
118 return 5;
119}
120
121int StandardCoordinateReferenceSystemsModel::columnCount( const QModelIndex & ) const
122{
123 return 1;
124}
125
126QModelIndex StandardCoordinateReferenceSystemsModel::index( int row, int column, const QModelIndex &parent ) const
127{
128 if ( row < 0 || row >= rowCount() || column != 0 || parent.isValid() )
129 return QModelIndex();
130
131 return createIndex( row, column );
132}
133
134QModelIndex StandardCoordinateReferenceSystemsModel::parent( const QModelIndex & ) const
135{
136 return QModelIndex();
137}
138
139QgsCoordinateReferenceSystem StandardCoordinateReferenceSystemsModel::crs( const QModelIndex &index ) const
140{
141 if ( !index.isValid() )
143
144 const QgsProjectionSelectionWidget::CrsOption option = optionForIndex( index );
145 switch ( option )
146 {
148 return mProjectCrs;
150 return mDefaultCrs;
152 return mCurrentCrs;
154 return mLayerCrs;
159 }
161}
162
163QgsProjectionSelectionWidget::CrsOption StandardCoordinateReferenceSystemsModel::optionForIndex( const QModelIndex &index ) const
164{
165 if ( !index.isValid() )
167
168 const int row = index.row();
169 switch ( row )
170 {
171 case 0:
173 case 1:
175 case 2:
177 case 3:
179 case 4:
181 default:
182 break;
183 }
184
186}
187
188QModelIndex StandardCoordinateReferenceSystemsModel::indexForOption( QgsProjectionSelectionWidget::CrsOption option ) const
189{
190 int row = 0;
191 switch ( option )
192 {
195 return QModelIndex();
197 row = 0;
198 break;
200 row = 1;
201 break;
203 row = 2;
204 break;
206 row = 3;
207 break;
209 row = 4;
210 break;
211 }
212
213 return index( row, 0, QModelIndex() );
214}
215
216void StandardCoordinateReferenceSystemsModel::setLayerCrs( const QgsCoordinateReferenceSystem &crs )
217{
218 mLayerCrs = crs;
219 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::LayerCrs );
220 emit dataChanged( index, index );
221}
222
223void StandardCoordinateReferenceSystemsModel::setCurrentCrs( const QgsCoordinateReferenceSystem &crs )
224{
225 mCurrentCrs = crs;
226 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::LayerCrs );
227 emit dataChanged( index, index );
228}
229
230void StandardCoordinateReferenceSystemsModel::setNotSetText( const QString &text )
231{
232 mNotSetText = text;
233 const QModelIndex index = indexForOption( QgsProjectionSelectionWidget::CrsNotSet );
234 emit dataChanged( index, index );
235}
236
237//
238// CombinedCoordinateReferenceSystemsModel
239//
240
241CombinedCoordinateReferenceSystemsModel::CombinedCoordinateReferenceSystemsModel( QObject *parent )
242 : QConcatenateTablesProxyModel( parent )
243 , mStandardModel( new StandardCoordinateReferenceSystemsModel( this ) )
244 , mRecentModel( new QgsRecentCoordinateReferenceSystemsProxyModel( this ) )
245{
246 addSourceModel( mStandardModel );
247 addSourceModel( mRecentModel );
248}
249
250void CombinedCoordinateReferenceSystemsModel::setNotSetText( const QString &text )
251{
252 mStandardModel->setNotSetText( text );
253}
254
255QString CombinedCoordinateReferenceSystemsModel::notSetText() const
256{
257 return mStandardModel->notSetText();
258}
259
260QgsCoordinateReferenceSystem CombinedCoordinateReferenceSystemsModel::currentCrs() const
261{
262 return mStandardModel->currentCrs();
263}
264
265//
266// CombinedCoordinateReferenceSystemsProxyModel
267//
268CombinedCoordinateReferenceSystemsProxyModel::CombinedCoordinateReferenceSystemsProxyModel( QObject *parent )
269 : QSortFilterProxyModel( parent )
270 , mModel( new CombinedCoordinateReferenceSystemsModel( this ) )
271{
272 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::CurrentCrs, true );
273 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::ProjectCrs, true );
274 mVisibleOptions.setFlag( QgsProjectionSelectionWidget::DefaultCrs, true );
275
276 setSourceModel( mModel );
277 setDynamicSortFilter( true );
278}
279
280bool CombinedCoordinateReferenceSystemsProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const
281{
282 const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
283
284 const QgsCoordinateReferenceSystem crs = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
285 if ( !mFilteredCrs.isEmpty() && !mFilteredCrs.contains( crs ) )
286 return false;
287
288 switch ( crs.type() )
289 {
292 break;
293
297 return false;
299 return false;
300 break;
301
305 return false;
306 break;
307
314 return false;
315 break;
316
319 return false;
320 break;
321
324 return false;
325 break;
326 }
327
328 const QVariant optionInt = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleOption );
329 if ( optionInt.isValid() )
330 {
331 if ( optionInt.toInt() > 0 )
332 {
333 const QgsProjectionSelectionWidget::CrsOption option = static_cast<QgsProjectionSelectionWidget::CrsOption>( optionInt.toInt() );
334 if ( !mVisibleOptions.testFlag( option ) )
335 return false;
336
337 // specific logic for showing/hiding options:
338 switch ( option )
339 {
341 break;
342
345 // only show these options if the crs is valid
346 return crs.isValid();
347
349 // prevent adding "no projection"/invalid entry in the base crs widget of topocentric crs
351 return crs.isValid();
352 // hide invalid current CRS value option only if "not set" option is shown
353 return crs.isValid() || !mVisibleOptions.testFlag( QgsProjectionSelectionWidget::CrsNotSet );
354
358 // always shown
359 break;
360 }
361 return true;
362 }
363 }
364 else
365 {
366 // a recent crs
367 // these are only shown if they aren't duplicates of a standard item already shown in the list
368 for ( QgsProjectionSelectionWidget::CrsOption standardOption :
373 {
374 const QModelIndexList standardItemIndex = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption, static_cast<int>( standardOption ) );
375 if ( standardItemIndex.empty() )
376 continue;
377
378 const QgsCoordinateReferenceSystem standardItemCrs = mModel->data( standardItemIndex.at( 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
379 if ( standardItemCrs == crs && filterAcceptsRow( standardItemIndex.at( 0 ).row(), QModelIndex() ) )
380 return false;
381 }
382 }
383
384 return true;
385}
386
387void CombinedCoordinateReferenceSystemsProxyModel::setLayerCrs( const QgsCoordinateReferenceSystem &crs )
388{
389 mModel->standardModel()->setLayerCrs( crs );
390 invalidateFilter();
391}
392
393void CombinedCoordinateReferenceSystemsProxyModel::setCurrentCrs( const QgsCoordinateReferenceSystem &crs )
394{
395 mModel->standardModel()->setCurrentCrs( crs );
396 invalidateFilter();
397}
398
399void CombinedCoordinateReferenceSystemsProxyModel::setFilters( QgsCoordinateReferenceSystemProxyModel::Filters filters )
400{
401 mFilters = filters;
402 invalidateFilter();
403}
404
405QgsCoordinateReferenceSystemProxyModel::Filters CombinedCoordinateReferenceSystemsProxyModel::filters() const
406{
407 return mFilters;
408}
409
410void CombinedCoordinateReferenceSystemsProxyModel::setFilteredCrs( const QList<QgsCoordinateReferenceSystem> &crses )
411{
412 mFilteredCrs = crses;
413 invalidateFilter();
414}
415
416void CombinedCoordinateReferenceSystemsProxyModel::setOption( QgsProjectionSelectionWidget::CrsOption option, bool enabled )
417{
418 mVisibleOptions.setFlag( option, enabled );
419 invalidateFilter();
420}
421
423
424
426 : QWidget( parent )
427 , mDialogTitle( tr( "Coordinate Reference System Selector" ) )
428{
429 mCrsComboBox = new QgsHighlightableComboBox( this );
430 mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
431
432 mModel = new CombinedCoordinateReferenceSystemsProxyModel( this );
433 mModel->setFilters( filters );
434 mCrsComboBox->setModel( mModel );
435
436 const int labelMargin = static_cast<int>( std::round( mCrsComboBox->fontMetrics().horizontalAdvance( 'X' ) ) );
437 QHBoxLayout *layout = new QHBoxLayout();
438 layout->setContentsMargins( 0, 0, 0, 0 );
439 layout->setSpacing( 0 );
440 setLayout( layout );
441
442 layout->addWidget( mCrsComboBox, 1 );
443
444 // bit of fiddlyness here -- we want the initial spacing to only be visible
445 // when the warning label is shown, so it's embedded inside mWarningLabel
446 // instead of outside it
447 mWarningLabelContainer = new QWidget();
448 QHBoxLayout *warningLayout = new QHBoxLayout();
449 warningLayout->setContentsMargins( 0, 0, 0, 0 );
450 mWarningLabel = new QLabel();
451 const QIcon icon = QgsApplication::getThemeIcon( u"mIconWarning.svg"_s );
452 const int size = static_cast<int>( std::max( 24.0, mCrsComboBox->minimumSize().height() * 0.5 ) );
453 mWarningLabel->setPixmap( icon.pixmap( icon.actualSize( QSize( size, size ) ) ) );
454 warningLayout->insertSpacing( 0, labelMargin / 2 );
455 warningLayout->insertWidget( 1, mWarningLabel );
456 mWarningLabelContainer->setLayout( warningLayout );
457 layout->addWidget( mWarningLabelContainer );
458 mWarningLabelContainer->hide();
459
460 layout->addSpacing( labelMargin / 2 );
461
462 mButton = new QToolButton( this );
463 mButton->setIcon( QgsApplication::getThemeIcon( u"mActionSetProjection.svg"_s ) );
464 mButton->setToolTip( tr( "Select CRS" ) );
465 layout->addWidget( mButton );
466
467 setFocusPolicy( Qt::StrongFocus );
468 setFocusProxy( mButton );
469 setAcceptDrops( true );
470
471 connect( mButton, &QToolButton::clicked, this, &QgsProjectionSelectionWidget::selectCrs );
472 connect( mCrsComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsProjectionSelectionWidget::comboIndexChanged );
473}
474
476{
477 const int idx = mCrsComboBox->currentIndex();
478 if ( idx >= 0 && idx < mModel->rowCount() )
479 return mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
480 else
482}
483
485{
486 switch ( option )
487 {
492 {
493 mModel->setOption( option, visible );
494 updateTooltip();
495 return;
496 }
498 //recently used CRS option cannot be readded
499 return;
501 {
502 mModel->setOption( CrsNotSet, visible );
503
504 if ( !visible )
505 {
507 }
508 else
509 {
510 if ( !mModel->combinedModel()->currentCrs().isValid() )
511 whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
512 }
513 updateTooltip();
514
515 return;
516 }
517 case Invalid:
518 return;
519 }
520}
521
523{
524 mModel->combinedModel()->setNotSetText( text );
525}
526
528{
529 mMessage = text;
530}
531
533{
534 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption, static_cast<int>( option ) );
535 return !matches.empty();
536}
537
539{
540 mAllowTopocentricCrs = allow;
541}
542
544{
546 const QList<QgsCoordinateReferenceSystem> filteredCrses = mModel->filteredCrs();
547
548 QSet<QString> ogcFilter;
549 ogcFilter.reserve( filteredCrses.size() );
550 for ( const QgsCoordinateReferenceSystem &crs : std::as_const( filteredCrses ) )
551 {
552 ogcFilter << crs.authid();
553 }
554
555 if ( panel && panel->dockMode() )
556 {
557 mActivePanel = new QgsCrsSelectionWidget( this, mModel->filters() );
558 if ( !ogcFilter.isEmpty() )
559 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
560 if ( !mMessage.isEmpty() )
561 mActivePanel->setMessage( mMessage );
562 mActivePanel->setCrs( crs() );
563
564 if ( !mModel->combinedModel()->notSetText().isEmpty() )
565 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
566
567 mActivePanel->setPanelTitle( mDialogTitle );
568
569 if ( !mAllowTopocentricCrs )
570 mActivePanel->setAllowTopocentricCrs( false );
571
573 {
574 mActivePanel->setShowNoCrs( true );
575 }
576
577 connect( mActivePanel, &QgsCrsSelectionWidget::crsChanged, this, [this] {
578 if ( mIgnorePanelSignals )
579 return;
580
581 if ( !mActivePanel->hasValidSelection() )
582 return;
583
584 mCrsComboBox->blockSignals( true );
585 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
586 mCrsComboBox->blockSignals( false );
587 const QgsCoordinateReferenceSystem crs = mActivePanel->crs();
588
589 mIgnorePanelSignals++;
590 setCrs( crs );
591 mIgnorePanelSignals--;
592
593 emit crsChanged( crs );
594 } );
595 panel->openPanel( mActivePanel );
596 }
597 else
598 {
599 QgsProjectionSelectionDialog dlg( this, QgsGuiUtils::ModalDialogFlags, mModel->filters() );
600 if ( !mMessage.isEmpty() )
601 dlg.setMessage( mMessage );
602 if ( !ogcFilter.isEmpty() )
603 dlg.setOgcWmsCrsFilter( ogcFilter );
604 dlg.setCrs( crs() );
605 dlg.setWindowTitle( mDialogTitle );
606
607 if ( !mAllowTopocentricCrs )
608 dlg.setAllowTopocentricCrs( false );
609
610 if ( !mModel->combinedModel()->notSetText().isEmpty() )
611 dlg.setNotSetText( mModel->combinedModel()->notSetText() );
612
614 {
615 dlg.setShowNoProjection( true );
616 }
618
619 if ( dlg.exec() )
620 {
621 mCrsComboBox->blockSignals( true );
622 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
623 mCrsComboBox->blockSignals( false );
625 // setCrs will emit crsChanged for us
626 setCrs( crs );
627 }
628 else
629 {
630 QApplication::restoreOverrideCursor();
631 }
632 }
633}
634
636{
637 if ( !( event->possibleActions() & Qt::CopyAction ) )
638 {
639 event->ignore();
640 return;
641 }
642
643 if ( mapLayerFromMimeData( event->mimeData() ) )
644 {
645 // dragged an acceptable layer, phew
646 event->setDropAction( Qt::CopyAction );
647 event->accept();
648 mCrsComboBox->setHighlighted( true );
649 update();
650 }
651 else
652 {
653 event->ignore();
654 }
655}
656
658{
659 if ( mCrsComboBox->isHighlighted() )
660 {
661 event->accept();
662 mCrsComboBox->setHighlighted( false );
663 update();
664 }
665 else
666 {
667 event->ignore();
668 }
669}
670
672{
673 if ( !( event->possibleActions() & Qt::CopyAction ) )
674 {
675 event->ignore();
676 return;
677 }
678
679 if ( QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
680 {
681 // dropped a map layer
682 setFocus( Qt::MouseFocusReason );
683 event->setDropAction( Qt::CopyAction );
684 event->accept();
685
686 if ( layer->crs().isValid() )
687 setCrs( layer->crs() );
688 }
689 else
690 {
691 event->ignore();
692 }
693 mCrsComboBox->setHighlighted( false );
694 update();
695}
696
698{
699 return mSourceEnsemble;
700}
701
703{
704 mDialogTitle = title;
705}
706
708{
709 return mDialogTitle;
710}
711
712void QgsProjectionSelectionWidget::setFilter( const QList<QgsCoordinateReferenceSystem> &crses )
713{
714 mModel->setFilteredCrs( crses );
715}
716
721
723{
724 mModel->setFilters( filters );
725 if ( mActivePanel )
726 mActivePanel->setFilters( filters );
727}
728
730{
731 if ( mSourceEnsemble == ensemble )
732 return;
733
734 mSourceEnsemble = ensemble;
735 updateWarning();
736}
737
739{
740 return mShowAccuracyWarnings;
741}
742
744{
745 mShowAccuracyWarnings = show;
746 if ( !mShowAccuracyWarnings )
747 mWarningLabelContainer->hide();
748 else
749 updateWarning();
750}
751
752void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
753{
754 if ( idx >= 0 && idx < mModel->rowCount() )
755 {
756 const QgsCoordinateReferenceSystem crs = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
757 const QVariant optionData = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption );
758 if ( !optionData.isValid() || static_cast<CrsOption>( optionData.toInt() ) != QgsProjectionSelectionWidget::CrsNotSet )
759 {
760 // RoleOption is only available for items from the standard coordinate reference system model, but we
761 // are using a combined model which also has items from QgsRecentCoordinateReferenceSystemsModel
762 emit crsChanged( crs );
763 }
764 else
765 {
766 emit cleared();
767 emit crsChanged( QgsCoordinateReferenceSystem() );
768 }
769 }
770
771 updateTooltip();
772}
773
774void QgsProjectionSelectionWidget::updateWarning()
775{
776 if ( !mShowAccuracyWarnings )
777 {
778 if ( mWarningLabelContainer->isVisible() )
779 mWarningLabelContainer->hide();
780 return;
781 }
782
783 try
784 {
785 const double crsAccuracyWarningThreshold = QgsSettings().value( u"/projections/crsAccuracyWarningThreshold"_s, 0.0, QgsSettings::App ).toDouble();
786
787 const QgsDatumEnsemble ensemble = crs().datumEnsemble();
788 if ( !ensemble.isValid() || ensemble.name() == mSourceEnsemble || ( ensemble.accuracy() > 0 && ensemble.accuracy() < crsAccuracyWarningThreshold ) )
789 {
790 mWarningLabelContainer->hide();
791 }
792 else
793 {
794 mWarningLabelContainer->show();
795
796 QString warning = u"<p>"_s;
797
798 QString id;
799 if ( !ensemble.code().isEmpty() )
800 id = u"<i>%1</i> (%2:%3)"_s.arg( ensemble.name(), ensemble.authority(), ensemble.code() );
801 else
802 id = u"<i>%1</i>”"_s.arg( ensemble.name() );
803
804 if ( ensemble.accuracy() > 0 )
805 {
806 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() );
807 }
808 else
809 {
810 warning = tr( "The selected CRS is based on %1, which has a limited accuracy." ).arg( id );
811 }
812 warning += u"</p><p>"_s + tr( "Use an alternative CRS if accurate positioning is required." ) + u"</p>"_s;
813
814 const QList<QgsDatumEnsembleMember> members = ensemble.members();
815 if ( !members.isEmpty() )
816 {
817 warning += u"<p>"_s + tr( "%1 consists of the datums:" ).arg( ensemble.name() ) + u"</p><ul>"_s;
818
819 for ( const QgsDatumEnsembleMember &member : members )
820 {
821 if ( !member.code().isEmpty() )
822 id = u"%1 (%2:%3)"_s.arg( member.name(), member.authority(), member.code() );
823 else
824 id = member.name();
825 warning += u"<li>%1</li>"_s.arg( id );
826 }
827
828 warning += "</ul>"_L1;
829 }
830
831 mWarningLabel->setToolTip( warning );
832 }
833 }
834 catch ( QgsNotSupportedException & )
835 {
836 mWarningLabelContainer->hide();
837 }
838}
839
841{
842 const QgsCoordinateReferenceSystem prevCrs = mModel->combinedModel()->currentCrs();
843 mModel->setCurrentCrs( crs );
844
845 if ( crs.isValid() )
846 {
848 mCrsComboBox->blockSignals( true );
849 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
850 mCrsComboBox->blockSignals( false );
851 }
852 else
853 {
854 const int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet, StandardCoordinateReferenceSystemsModel::Role::RoleOption );
855 if ( crsNotSetIndex >= 0 )
856 {
857 mCrsComboBox->blockSignals( true );
858 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
859 mCrsComboBox->blockSignals( false );
860 }
861 }
862 if ( mActivePanel && !mIgnorePanelSignals )
863 {
864 mIgnorePanelSignals++;
865 mActivePanel->setCrs( crs );
866 mIgnorePanelSignals--;
867 }
868 if ( prevCrs != crs )
869 {
870 emit crsChanged( crs );
871 }
872 updateTooltip();
873}
874
876{
877 mModel->setLayerCrs( crs );
878}
879
881{
882 if ( crs.isValid() )
883 return crs.userFriendlyIdentifier();
884 else
885 return tr( "invalid projection" );
886}
887
888void QgsProjectionSelectionWidget::updateTooltip()
889{
891 if ( c.isValid() )
892 setToolTip( c.toWkt( Qgis::CrsWktVariant::Preferred, true ) );
893 else
894 setToolTip( QString() );
895 updateWarning();
896}
897
898QgsMapLayer *QgsProjectionSelectionWidget::mapLayerFromMimeData( const QMimeData *data ) const
899{
901 for ( const QgsMimeDataUtils::Uri &u : uriList )
902 {
903 // is this uri from the current project?
904 if ( QgsMapLayer *layer = u.mapLayer() )
905 {
906 return layer;
907 }
908 }
909 return nullptr;
910}
@ Vertical
Vertical CRS.
Definition qgis.h:2482
@ Temporal
Temporal CRS.
Definition qgis.h:2485
@ Compound
Compound (horizontal + vertical) CRS.
Definition qgis.h:2484
@ Projected
Projected CRS.
Definition qgis.h:2483
@ Other
Other type.
Definition qgis.h:2488
@ Bound
Bound CRS.
Definition qgis.h:2487
@ DerivedProjected
Derived projected CRS.
Definition qgis.h:2489
@ Unknown
Unknown type.
Definition qgis.h:2477
@ Engineering
Engineering CRS.
Definition qgis.h:2486
@ Geographic3d
3D geopraphic CRS
Definition qgis.h:2481
@ Geodetic
Geodetic CRS.
Definition qgis.h:2478
@ Geographic2d
2D geographic CRS
Definition qgis.h:2480
@ Geocentric
Geocentric CRS.
Definition qgis.h:2479
static QString geographicCrsAuthId()
Geographic coordinate system auth:id string for a default geographic CRS (EPSG:4326).
Definition qgis.h:7102
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition qgis.h:2594
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).
@ FilterTopocentricCompatible
Include all CRS types compatible with topocentric CRS (all except projected CRS).
@ 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:126
QString authority() const
Authority name, e.g.
Definition qgsdatums.h:121
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:106
QList< QgsDatumEnsembleMember > members() const
Contains a list of members of the ensemble.
Definition qgsdatums.h:141
QString name() const
Display name of datum ensemble.
Definition qgsdatums.h:111
double accuracy() const
Positional accuracy (in meters).
Definition qgsdatums.h:116
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:114
static QgsProject * instance()
Returns the QgsProject singleton instance.
void crsChanged()
Emitted when the crs() of the project has changed.
QgsCoordinateReferenceSystem crs
Definition qgsproject.h:120
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 setAllowTopocentricCrs(bool allow)
Sets whether the topocentric CRS type option is shown in the dialog.
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.
void setAllowTopocentricCrs(bool allow)
Sets whether the topocentric CRS option is allowed in the CRS selector dialog opened by the widget's ...
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:8015
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:7275