QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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 "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 );
67 if ( option == QgsProjectionSelectionWidget::CrsOption::Invalid )
68 return QVariant();
69
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
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
296 if ( !mFilters.testFlag( QgsCoordinateReferenceSystemProxyModel::Filter::FilterHorizontal ) )
297 return false;
298 break;
299
301 if ( !mFilters.testFlag( QgsCoordinateReferenceSystemProxyModel::Filter::FilterVertical ) )
302 return false;
303 break;
304
306 if ( !mFilters.testFlag( QgsCoordinateReferenceSystemProxyModel::Filter::FilterCompound ) )
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 {
350 QgsProjectionSelectionWidget::CrsOption::CurrentCrs,
351 QgsProjectionSelectionWidget::CrsOption::DefaultCrs,
352 QgsProjectionSelectionWidget::CrsOption::LayerCrs,
353 QgsProjectionSelectionWidget::CrsOption::ProjectCrs
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
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 updateTooltip();
474 return;
475 }
477 //recently used CRS option cannot be readded
478 return;
480 {
481 mModel->setOption( CrsNotSet, visible );
482
483 if ( !visible )
484 {
486 }
487 else
488 {
489 if ( !mModel->combinedModel()->currentCrs().isValid() )
490 whileBlocking( mCrsComboBox )->setCurrentIndex( 0 );
491 }
492 updateTooltip();
493
494 return;
495 }
496 case Invalid:
497 return;
498 }
499}
500
502{
503 mModel->combinedModel()->setNotSetText( text );
504}
505
507{
508 mMessage = text;
509}
510
512{
513 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption, static_cast< int >( option ) );
514 return !matches.empty();
515}
516
518{
520 const QList< QgsCoordinateReferenceSystem > filteredCrses = mModel->filteredCrs();
521
522 QSet< QString > ogcFilter;
523 ogcFilter.reserve( filteredCrses.size( ) );
524 for ( const QgsCoordinateReferenceSystem &crs : std::as_const( filteredCrses ) )
525 {
526 ogcFilter << crs.authid();
527 }
528
529 if ( panel && panel->dockMode() )
530 {
531 mActivePanel = new QgsCrsSelectionWidget( this, mModel->filters() );
532 if ( !ogcFilter.isEmpty() )
533 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
534 if ( !mMessage.isEmpty() )
535 mActivePanel->setMessage( mMessage );
536 mActivePanel->setCrs( crs() );
537
538 if ( !mModel->combinedModel()->notSetText().isEmpty() )
539 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
540
541 mActivePanel->setPanelTitle( mDialogTitle );
542
543 if ( optionVisible( QgsProjectionSelectionWidget::CrsOption::CrsNotSet ) )
544 {
545 mActivePanel->setShowNoCrs( true );
546 }
547
548 connect( mActivePanel, &QgsCrsSelectionWidget::crsChanged, this, [ this ]
549 {
550 if ( mIgnorePanelSignals )
551 return;
552
553 if ( !mActivePanel->hasValidSelection() )
554 return;
555
556 mCrsComboBox->blockSignals( true );
557 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
558 mCrsComboBox->blockSignals( false );
559 const QgsCoordinateReferenceSystem crs = mActivePanel->crs();
560
561 mIgnorePanelSignals++;
562 setCrs( crs );
563 mIgnorePanelSignals--;
564
565 emit crsChanged( crs );
566 } );
567 panel->openPanel( mActivePanel );
568 }
569 else
570 {
571 QgsProjectionSelectionDialog dlg( this, QgsGuiUtils::ModalDialogFlags, mModel->filters() );
572 if ( !mMessage.isEmpty() )
573 dlg.setMessage( mMessage );
574 if ( !ogcFilter.isEmpty() )
575 dlg.setOgcWmsCrsFilter( ogcFilter );
576 dlg.setCrs( crs() );
577 dlg.setWindowTitle( mDialogTitle );
578
579 if ( !mModel->combinedModel()->notSetText().isEmpty() )
580 dlg.setNotSetText( mModel->combinedModel()->notSetText() );
581
582 if ( optionVisible( QgsProjectionSelectionWidget::CrsOption::CrsNotSet ) )
583 {
584 dlg.setShowNoProjection( true );
585 }
587
588 if ( dlg.exec() )
589 {
590 mCrsComboBox->blockSignals( true );
591 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
592 mCrsComboBox->blockSignals( false );
594 // setCrs will emit crsChanged for us
595 setCrs( crs );
596 }
597 else
598 {
599 QApplication::restoreOverrideCursor();
600 }
601 }
602}
603
605{
606 if ( !( event->possibleActions() & Qt::CopyAction ) )
607 {
608 event->ignore();
609 return;
610 }
611
612 if ( mapLayerFromMimeData( event->mimeData() ) )
613 {
614 // dragged an acceptable layer, phew
615 event->setDropAction( Qt::CopyAction );
616 event->accept();
617 mCrsComboBox->setHighlighted( true );
618 update();
619 }
620 else
621 {
622 event->ignore();
623 }
624}
625
627{
628 if ( mCrsComboBox->isHighlighted() )
629 {
630 event->accept();
631 mCrsComboBox->setHighlighted( false );
632 update();
633 }
634 else
635 {
636 event->ignore();
637 }
638}
639
641{
642 if ( !( event->possibleActions() & Qt::CopyAction ) )
643 {
644 event->ignore();
645 return;
646 }
647
648 if ( QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
649 {
650 // dropped a map layer
651 setFocus( Qt::MouseFocusReason );
652 event->setDropAction( Qt::CopyAction );
653 event->accept();
654
655 if ( layer->crs().isValid() )
656 setCrs( layer->crs() );
657 }
658 else
659 {
660 event->ignore();
661 }
662 mCrsComboBox->setHighlighted( false );
663 update();
664}
665
667{
668 return mSourceEnsemble;
669}
670
672{
673 mDialogTitle = title;
674}
675
677{
678 return mDialogTitle;
679}
680
681void QgsProjectionSelectionWidget::setFilter( const QList<QgsCoordinateReferenceSystem> &crses )
682{
683 mModel->setFilteredCrs( crses );
684}
685
687{
688 return mModel->filters();
689}
690
692{
693 mModel->setFilters( filters );
694 if ( mActivePanel )
695 mActivePanel->setFilters( filters );
696}
697
699{
700 if ( mSourceEnsemble == ensemble )
701 return;
702
703 mSourceEnsemble = ensemble;
704 updateWarning();
705}
706
708{
709 return mShowAccuracyWarnings;
710}
711
713{
714 mShowAccuracyWarnings = show;
715 if ( !mShowAccuracyWarnings )
716 mWarningLabelContainer->hide();
717 else
718 updateWarning();
719}
720
721void QgsProjectionSelectionWidget::comboIndexChanged( int idx )
722{
723 const QgsCoordinateReferenceSystem crs = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value< QgsCoordinateReferenceSystem >();
724 const QVariant optionData = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption );
725 if ( !optionData.isValid() || static_cast< CrsOption >( optionData.toInt() ) != QgsProjectionSelectionWidget::CrsNotSet )
726 {
727 // RoleOption is only available for items from the standard coordinate reference system model, but we
728 // are using a combined model which also has items from QgsRecentCoordinateReferenceSystemsModel
729 emit crsChanged( crs );
730 }
731 else
732 {
733 emit cleared();
735 }
736 updateTooltip();
737}
738
739void QgsProjectionSelectionWidget::updateWarning()
740{
741 if ( !mShowAccuracyWarnings )
742 {
743 if ( mWarningLabelContainer->isVisible() )
744 mWarningLabelContainer->hide();
745 return;
746 }
747
748 try
749 {
750 const double crsAccuracyWarningThreshold = QgsSettings().value( QStringLiteral( "/projections/crsAccuracyWarningThreshold" ), 0.0, QgsSettings::App ).toDouble();
751
752 const QgsDatumEnsemble ensemble = crs().datumEnsemble();
753 if ( !ensemble.isValid() || ensemble.name() == mSourceEnsemble || ( ensemble.accuracy() > 0 && ensemble.accuracy() < crsAccuracyWarningThreshold ) )
754 {
755 mWarningLabelContainer->hide();
756 }
757 else
758 {
759 mWarningLabelContainer->show();
760
761 QString warning = QStringLiteral( "<p>" );
762
763 QString id;
764 if ( !ensemble.code().isEmpty() )
765 id = QStringLiteral( "<i>%1</i> (%2:%3)" ).arg( ensemble.name(), ensemble.authority(), ensemble.code() );
766 else
767 id = QStringLiteral( "<i>%</i>”" ).arg( ensemble.name() );
768
769 if ( ensemble.accuracy() > 0 )
770 {
771 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() );
772 }
773 else
774 {
775 warning = tr( "The selected CRS is based on %1, which has a limited accuracy." ).arg( id );
776 }
777 warning += QStringLiteral( "</p><p>" ) + tr( "Use an alternative CRS if accurate positioning is required." ) + QStringLiteral( "</p>" );
778
779 const QList< QgsDatumEnsembleMember > members = ensemble.members();
780 if ( !members.isEmpty() )
781 {
782 warning += QStringLiteral( "<p>" ) + tr( "%1 consists of the datums:" ).arg( ensemble.name() ) + QStringLiteral( "</p><ul>" );
783
784 for ( const QgsDatumEnsembleMember &member : members )
785 {
786 if ( !member.code().isEmpty() )
787 id = QStringLiteral( "%1 (%2:%3)" ).arg( member.name(), member.authority(), member.code() );
788 else
789 id = member.name();
790 warning += QStringLiteral( "<li>%1</li>" ).arg( id );
791 }
792
793 warning += QLatin1String( "</ul>" );
794 }
795
796 mWarningLabel->setToolTip( warning );
797 }
798 }
799 catch ( QgsNotSupportedException & )
800 {
801 mWarningLabelContainer->hide();
802 }
803}
804
806{
807 const QgsCoordinateReferenceSystem prevCrs = mModel->combinedModel()->currentCrs();
808 mModel->setCurrentCrs( crs );
809
810 if ( crs.isValid() )
811 {
813 mCrsComboBox->blockSignals( true );
814 mCrsComboBox->setCurrentIndex( mCrsComboBox->findData( QgsProjectionSelectionWidget::CurrentCrs, StandardCoordinateReferenceSystemsModel::Role::RoleOption ) );
815 mCrsComboBox->blockSignals( false );
816 }
817 else
818 {
819 const int crsNotSetIndex = mCrsComboBox->findData( QgsProjectionSelectionWidget::CrsNotSet, StandardCoordinateReferenceSystemsModel::Role::RoleOption );
820 if ( crsNotSetIndex >= 0 )
821 {
822 mCrsComboBox->blockSignals( true );
823 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
824 mCrsComboBox->blockSignals( false );
825 }
826 }
827 if ( mActivePanel && !mIgnorePanelSignals )
828 {
829 mIgnorePanelSignals++;
830 mActivePanel->setCrs( crs );
831 mIgnorePanelSignals--;
832 }
833 if ( prevCrs != crs )
834 {
835 emit crsChanged( crs );
836 }
837 updateTooltip();
838}
839
841{
842 mModel->setLayerCrs( crs );
843}
844
846{
847 if ( crs.isValid() )
849 else
850 return tr( "invalid projection" );
851}
852
853void QgsProjectionSelectionWidget::updateTooltip()
854{
856 if ( c.isValid() )
857 setToolTip( c.toWkt( Qgis::CrsWktVariant::Preferred, true ) );
858 else
859 setToolTip( QString() );
860 updateWarning();
861}
862
863QgsMapLayer *QgsProjectionSelectionWidget::mapLayerFromMimeData( const QMimeData *data ) const
864{
866 for ( const QgsMimeDataUtils::Uri &u : uriList )
867 {
868 // is this uri from the current project?
869 if ( QgsMapLayer *layer = u.mapLayer() )
870 {
871 return layer;
872 }
873 }
874 return nullptr;
875}
876
@ 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...
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.
Definition: qgsexception.h:118
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:5853
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
Definition: qgis.h:5111
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
Definition: qgis.h:5688
const QgsCoordinateReferenceSystem & crs