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