QGIS API Documentation 3.36.0-Maidenhead (09951dc0acf)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
16#include <QHBoxLayout>
17
19#include "qgsapplication.h"
21#include "qgsproject.h"
22#include "qgssettings.h"
26#include "qgsdatums.h"
27
28#ifdef ENABLE_MODELTEST
29#include "modeltest.h"
30#endif
31
32
34StandardCoordinateReferenceSystemsModel::StandardCoordinateReferenceSystemsModel( QObject *parent )
35 : QAbstractItemModel( parent )
36 , mProjectCrs( QgsProject::instance()->crs() )
37{
38#ifdef ENABLE_MODELTEST
39 new ModelTest( this, this );
40#endif
41
42 const QgsSettings settings;
43 mDefaultCrs = QgsCoordinateReferenceSystem( settings.value( QStringLiteral( "/projections/defaultProjectCrs" ), geoEpsgCrsAuthId(), QgsSettings::App ).toString() );
44
46 {
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 QgsCoordinateReferenceSystemProxyModel::Filters filters )
409 : QWidget( parent )
410 , mDialogTitle( tr( "Coordinate Reference System Selector" ) )
411{
412 mCrsComboBox = new QgsHighlightableComboBox( this );
413 mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
414
415 mModel = new CombinedCoordinateReferenceSystemsProxyModel( this );
416 mModel->setFilters( filters );
417 mCrsComboBox->setModel( mModel );
418
419 const int labelMargin = static_cast< int >( std::round( mCrsComboBox->fontMetrics().horizontalAdvance( 'X' ) ) );
420 QHBoxLayout *layout = new QHBoxLayout();
421 layout->setContentsMargins( 0, 0, 0, 0 );
422 layout->setSpacing( 0 );
423 setLayout( layout );
424
425 layout->addWidget( mCrsComboBox, 1 );
426
427 // bit of fiddlyness here -- we want the initial spacing to only be visible
428 // when the warning label is shown, so it's embedded inside mWarningLabel
429 // instead of outside it
430 mWarningLabelContainer = new QWidget();
431 QHBoxLayout *warningLayout = new QHBoxLayout();
432 warningLayout->setContentsMargins( 0, 0, 0, 0 );
433 mWarningLabel = new QLabel();
434 const QIcon icon = QgsApplication::getThemeIcon( QStringLiteral( "mIconWarning.svg" ) );
435 const int size = static_cast< int >( std::max( 24.0, mCrsComboBox->minimumSize().height() * 0.5 ) );
436 mWarningLabel->setPixmap( icon.pixmap( icon.actualSize( QSize( size, size ) ) ) );
437 warningLayout->insertSpacing( 0, labelMargin / 2 );
438 warningLayout->insertWidget( 1, mWarningLabel );
439 mWarningLabelContainer->setLayout( warningLayout );
440 layout->addWidget( mWarningLabelContainer );
441 mWarningLabelContainer->hide();
442
443 layout->addSpacing( labelMargin / 2 );
444
445 mButton = new QToolButton( this );
446 mButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mActionSetProjection.svg" ) ) );
447 mButton->setToolTip( tr( "Select CRS" ) );
448 layout->addWidget( mButton );
449
450 setFocusPolicy( Qt::StrongFocus );
451 setFocusProxy( mButton );
452 setAcceptDrops( true );
453
454 connect( mButton, &QToolButton::clicked, this, &QgsProjectionSelectionWidget::selectCrs );
455 connect( mCrsComboBox, static_cast<void ( QComboBox::* )( int )>( &QComboBox::currentIndexChanged ), this, &QgsProjectionSelectionWidget::comboIndexChanged );
456}
457
459{
460 return mModel->data( mModel->index( mCrsComboBox->currentIndex(), 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value< QgsCoordinateReferenceSystem >();
461}
462
464{
465 switch ( option )
466 {
471 {
472 mModel->setOption( option, visible );
473 return;
474 }
476 //recently used CRS option cannot be readded
477 return;
479 {
480 mModel->setOption( CrsNotSet, visible );
481
482 if ( !visible )
483 {
485 }
486 else
487 {
488 if ( !mModel->combinedModel()->currentCrs().isValid() )
489 whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
490 }
491
492 return;
493 }
494 case Invalid:
495 return;
496 }
497}
498
500{
501 mModel->combinedModel()->setNotSetText( text );
502}
503
505{
506 mMessage = text;
507}
508
510{
511 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption, static_cast< int >( option ) );
512 return !matches.empty();
513}
514
516{
518 const QList< QgsCoordinateReferenceSystem > filteredCrses = mModel->filteredCrs();
519
520 QSet< QString > ogcFilter;
521 ogcFilter.reserve( filteredCrses.size( ) );
522 for ( const QgsCoordinateReferenceSystem &crs : std::as_const( filteredCrses ) )
523 {
524 ogcFilter << crs.authid();
525 }
526
527 if ( panel && panel->dockMode() )
528 {
529 mActivePanel = new QgsCrsSelectionWidget( this, mModel->filters() );
530 if ( !ogcFilter.isEmpty() )
531 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
532 if ( !mMessage.isEmpty() )
533 mActivePanel->setMessage( mMessage );
534 mActivePanel->setCrs( crs() );
535
536 if ( !mModel->combinedModel()->notSetText().isEmpty() )
537 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
538
539 mActivePanel->setPanelTitle( mDialogTitle );
540
542 {
543 mActivePanel->setShowNoCrs( true );
544 }
545
546 connect( mActivePanel, &QgsCrsSelectionWidget::crsChanged, this, [ this ]
547 {
548 if ( mIgnorePanelSignals )
549 return;
550
551 if ( !mActivePanel->hasValidSelection() )
552 return;
553
554 mCrsComboBox->blockSignals( true );
555 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
556 mCrsComboBox->blockSignals( false );
557 const QgsCoordinateReferenceSystem crs = mActivePanel->crs();
558
559 mIgnorePanelSignals++;
560 setCrs( crs );
561 mIgnorePanelSignals--;
562
563 emit crsChanged( crs );
564 } );
565 panel->openPanel( mActivePanel );
566 }
567 else
568 {
569 QgsProjectionSelectionDialog dlg( this, QgsGuiUtils::ModalDialogFlags, mModel->filters() );
570 if ( !mMessage.isEmpty() )
571 dlg.setMessage( mMessage );
572 if ( !ogcFilter.isEmpty() )
573 dlg.setOgcWmsCrsFilter( ogcFilter );
574 dlg.setCrs( crs() );
575 dlg.setWindowTitle( mDialogTitle );
576
577 if ( !mModel->combinedModel()->notSetText().isEmpty() )
578 dlg.setNotSetText( mModel->combinedModel()->notSetText() );
579
581 {
582 dlg.setShowNoProjection( true );
583 }
585
586 if ( dlg.exec() )
587 {
588 mCrsComboBox->blockSignals( true );
589 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
590 mCrsComboBox->blockSignals( false );
592 setCrs( crs );
593 emit crsChanged( crs );
594 }
595 else
596 {
597 QApplication::restoreOverrideCursor();
598 }
599 }
600}
601
603{
604 if ( !( event->possibleActions() & Qt::CopyAction ) )
605 {
606 event->ignore();
607 return;
608 }
609
610 if ( mapLayerFromMimeData( event->mimeData() ) )
611 {
612 // dragged an acceptable layer, phew
613 event->setDropAction( Qt::CopyAction );
614 event->accept();
615 mCrsComboBox->setHighlighted( true );
616 update();
617 }
618 else
619 {
620 event->ignore();
621 }
622}
623
625{
626 if ( mCrsComboBox->isHighlighted() )
627 {
628 event->accept();
629 mCrsComboBox->setHighlighted( false );
630 update();
631 }
632 else
633 {
634 event->ignore();
635 }
636}
637
639{
640 if ( !( event->possibleActions() & Qt::CopyAction ) )
641 {
642 event->ignore();
643 return;
644 }
645
646 if ( QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
647 {
648 // dropped a map layer
649 setFocus( Qt::MouseFocusReason );
650 event->setDropAction( Qt::CopyAction );
651 event->accept();
652
653 if ( layer->crs().isValid() )
654 setCrs( layer->crs() );
655 }
656 else
657 {
658 event->ignore();
659 }
660 mCrsComboBox->setHighlighted( false );
661 update();
662}
663
665{
666 return mSourceEnsemble;
667}
668
670{
671 mDialogTitle = title;
672}
673
675{
676 return mDialogTitle;
677}
678
679void QgsProjectionSelectionWidget::setFilter( const QList<QgsCoordinateReferenceSystem> &crses )
680{
681 mModel->setFilteredCrs( crses );
682}
683
684QgsCoordinateReferenceSystemProxyModel::Filters QgsProjectionSelectionWidget::filters() const
685{
686 return mModel->filters();
687}
688
689void QgsProjectionSelectionWidget::setFilters( QgsCoordinateReferenceSystemProxyModel::Filters filters )
690{
691 mModel->setFilters( filters );
692 if ( mActivePanel )
693 mActivePanel->setFilters( filters );
694}
695
697{
698 if ( mSourceEnsemble == ensemble )
699 return;
700
701 mSourceEnsemble = ensemble;
702 updateWarning();
703}
704
706{
707 return mShowAccuracyWarnings;
708}
709
711{
712 mShowAccuracyWarnings = show;
713 if ( !mShowAccuracyWarnings )
714 mWarningLabelContainer->hide();
715 else
716 updateWarning();
717}
718
719void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
720{
721 const QgsCoordinateReferenceSystem crs = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value< QgsCoordinateReferenceSystem >();
722 switch ( static_cast< CrsOption >( mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption ).toInt() ) )
723 {
730 emit crsChanged( crs );
731 break;
732
734 emit cleared();
736 break;
737 }
738 updateTooltip();
739}
740
741void QgsProjectionSelectionWidget::updateWarning()
742{
743 if ( !mShowAccuracyWarnings )
744 {
745 if ( mWarningLabelContainer->isVisible() )
746 mWarningLabelContainer->hide();
747 return;
748 }
749
750 try
751 {
752 const double crsAccuracyWarningThreshold = QgsSettings().value( QStringLiteral( "/projections/crsAccuracyWarningThreshold" ), 0.0, QgsSettings::App ).toDouble();
753
754 const QgsDatumEnsemble ensemble = crs().datumEnsemble();
755 if ( !ensemble.isValid() || ensemble.name() == mSourceEnsemble || ( ensemble.accuracy() > 0 && ensemble.accuracy() < crsAccuracyWarningThreshold ) )
756 {
757 mWarningLabelContainer->hide();
758 }
759 else
760 {
761 mWarningLabelContainer->show();
762
763 QString warning = QStringLiteral( "<p>" );
764
765 QString id;
766 if ( !ensemble.code().isEmpty() )
767 id = QStringLiteral( "<i>%1</i> (%2:%3)" ).arg( ensemble.name(), ensemble.authority(), ensemble.code() );
768 else
769 id = QStringLiteral( "<i>%</i>”" ).arg( ensemble.name() );
770
771 if ( ensemble.accuracy() > 0 )
772 {
773 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() );
774 }
775 else
776 {
777 warning = tr( "The selected CRS is based on %1, which has a limited accuracy." ).arg( id );
778 }
779 warning += QStringLiteral( "</p><p>" ) + tr( "Use an alternative CRS if accurate positioning is required." ) + QStringLiteral( "</p>" );
780
781 const QList< QgsDatumEnsembleMember > members = ensemble.members();
782 if ( !members.isEmpty() )
783 {
784 warning += QStringLiteral( "<p>" ) + tr( "%1 consists of the datums:" ).arg( ensemble.name() ) + QStringLiteral( "</p><ul>" );
785
786 for ( const QgsDatumEnsembleMember &member : members )
787 {
788 if ( !member.code().isEmpty() )
789 id = QStringLiteral( "%1 (%2:%3)" ).arg( member.name(), member.authority(), member.code() );
790 else
791 id = member.name();
792 warning += QStringLiteral( "<li>%1</li>" ).arg( id );
793 }
794
795 warning += QLatin1String( "</ul>" );
796 }
797
798 mWarningLabel->setToolTip( warning );
799 }
800 }
801 catch ( QgsNotSupportedException & )
802 {
803 mWarningLabelContainer->hide();
804 }
805}
806
808{
809 const QgsCoordinateReferenceSystem prevCrs = mModel->combinedModel()->currentCrs();
810 mModel->setCurrentCrs( crs );
811
812 if ( crs.isValid() )
813 {
815 mCrsComboBox->blockSignals( true );
816 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
817 mCrsComboBox->blockSignals( false );
818 }
819 else
820 {
821 const int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet, StandardCoordinateReferenceSystemsModel::Role::RoleOption );
822 if ( crsNotSetIndex >= 0 )
823 {
824 mCrsComboBox->blockSignals( true );
825 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
826 mCrsComboBox->blockSignals( false );
827 }
828 }
829 if ( mActivePanel && !mIgnorePanelSignals )
830 {
831 mIgnorePanelSignals++;
832 mActivePanel->setCrs( crs );
833 mIgnorePanelSignals--;
834 }
835 if ( prevCrs != crs )
836 {
837 emit crsChanged( crs );
838 }
839 updateTooltip();
840}
841
843{
844 mModel->setLayerCrs( crs );
845}
846
848{
849 if ( crs.isValid() )
851 else
852 return tr( "invalid projection" );
853}
854
855void QgsProjectionSelectionWidget::updateTooltip()
856{
858 if ( c.isValid() )
859 setToolTip( c.toWkt( Qgis::CrsWktVariant::Preferred, true ) );
860 else
861 setToolTip( QString() );
862 updateWarning();
863}
864
865QgsMapLayer *QgsProjectionSelectionWidget::mapLayerFromMimeData( const QMimeData *data ) const
866{
868 for ( const QgsMimeDataUtils::Uri &u : uriList )
869 {
870 // is this uri from the current project?
871 if ( QgsMapLayer *layer = u.mapLayer() )
872 {
873 return layer;
874 }
875 }
876 return nullptr;
877}
878
@ 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:75
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.
void crsChanged(const QgsCoordinateReferenceSystem &)
Emitted when the selected CRS is changed.
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 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:5790
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition qgis.h:5048
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
Definition qgis.h:5625
const QgsCoordinateReferenceSystem & crs