19#include "moc_qgsprojectionselectionwidget.cpp"
29#ifdef ENABLE_MODELTEST
35StandardCoordinateReferenceSystemsModel::StandardCoordinateReferenceSystemsModel( QObject *parent )
36 : QAbstractItemModel( parent )
39#ifdef ENABLE_MODELTEST
40 new ModelTest(
this,
this );
47 mCurrentCrs.updateDefinition();
48 mLayerCrs.updateDefinition();
49 mProjectCrs.updateDefinition();
50 mDefaultCrs.updateDefinition();
58Qt::ItemFlags StandardCoordinateReferenceSystemsModel::flags(
const QModelIndex &index )
const
60 if ( !index.isValid() )
62 return Qt::ItemFlags();
65 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
68QVariant StandardCoordinateReferenceSystemsModel::data(
const QModelIndex &index,
int role )
const
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() );
101 return static_cast<int>( option );
110int StandardCoordinateReferenceSystemsModel::rowCount(
const QModelIndex &parent )
const
112 if ( parent.isValid() )
118int StandardCoordinateReferenceSystemsModel::columnCount(
const QModelIndex & )
const
123QModelIndex StandardCoordinateReferenceSystemsModel::index(
int row,
int column,
const QModelIndex &parent )
const
125 if ( row < 0 || row >= rowCount() || column != 0 || parent.isValid() )
126 return QModelIndex();
128 return createIndex( row, column );
131QModelIndex StandardCoordinateReferenceSystemsModel::parent(
const QModelIndex & )
const
133 return QModelIndex();
138 if ( !index.isValid() )
162 if ( !index.isValid() )
165 const int row = index.row();
192 return QModelIndex();
210 return index( row, 0, QModelIndex() );
217 emit dataChanged( index, index );
224 emit dataChanged( index, index );
227void StandardCoordinateReferenceSystemsModel::setNotSetText(
const QString &text )
231 emit dataChanged( index, index );
238CombinedCoordinateReferenceSystemsModel::CombinedCoordinateReferenceSystemsModel( QObject *parent )
239 : QConcatenateTablesProxyModel( parent )
240 , mStandardModel( new StandardCoordinateReferenceSystemsModel( this ) )
243 addSourceModel( mStandardModel );
244 addSourceModel( mRecentModel );
247void CombinedCoordinateReferenceSystemsModel::setNotSetText(
const QString &text )
249 mStandardModel->setNotSetText( text );
252QString CombinedCoordinateReferenceSystemsModel::notSetText()
const
254 return mStandardModel->notSetText();
259 return mStandardModel->currentCrs();
265CombinedCoordinateReferenceSystemsProxyModel::CombinedCoordinateReferenceSystemsProxyModel( QObject *parent )
266 : QSortFilterProxyModel( parent )
267 , mModel( new CombinedCoordinateReferenceSystemsModel( this ) )
273 setSourceModel( mModel );
274 setDynamicSortFilter(
true );
277bool CombinedCoordinateReferenceSystemsProxyModel::filterAcceptsRow(
int sourceRow,
const QModelIndex &sourceParent )
const
279 const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
282 if ( !mFilteredCrs.isEmpty() && !mFilteredCrs.contains(
crs ) )
315 const QVariant optionInt = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleOption );
316 if ( optionInt.isValid() )
318 if ( optionInt.toInt() > 0 )
321 if ( !mVisibleOptions.testFlag( option ) )
360 const QModelIndexList standardItemIndex = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption,
static_cast<int>( standardOption ) );
361 if ( standardItemIndex.empty() )
364 const QgsCoordinateReferenceSystem standardItemCrs = mModel->data( standardItemIndex.at( 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<QgsCoordinateReferenceSystem>();
365 if ( standardItemCrs ==
crs && filterAcceptsRow( standardItemIndex.at( 0 ).row(), QModelIndex() ) )
375 mModel->standardModel()->setLayerCrs(
crs );
381 mModel->standardModel()->setCurrentCrs(
crs );
396void CombinedCoordinateReferenceSystemsProxyModel::setFilteredCrs(
const QList<QgsCoordinateReferenceSystem> &crses )
398 mFilteredCrs = crses;
404 mVisibleOptions.setFlag( option, enabled );
413 , mDialogTitle( tr(
"Coordinate Reference System Selector" ) )
416 mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
418 mModel =
new CombinedCoordinateReferenceSystemsProxyModel(
this );
420 mCrsComboBox->setModel( mModel );
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 );
428 layout->addWidget( mCrsComboBox, 1 );
433 mWarningLabelContainer =
new QWidget();
434 QHBoxLayout *warningLayout =
new QHBoxLayout();
435 warningLayout->setContentsMargins( 0, 0, 0, 0 );
436 mWarningLabel =
new QLabel();
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();
446 layout->addSpacing( labelMargin / 2 );
448 mButton =
new QToolButton(
this );
450 mButton->setToolTip( tr(
"Select CRS" ) );
451 layout->addWidget( mButton );
453 setFocusPolicy( Qt::StrongFocus );
454 setFocusProxy( mButton );
455 setAcceptDrops(
true );
458 connect( mCrsComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsProjectionSelectionWidget::comboIndexChanged );
463 const int idx = mCrsComboBox->currentIndex();
464 if ( idx >= 0 && idx < mModel->rowCount() )
479 mModel->setOption( option, visible );
496 if ( !mModel->combinedModel()->currentCrs().isValid() )
510 mModel->combinedModel()->setNotSetText( text );
520 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption,
static_cast<int>( option ) );
521 return !matches.empty();
527 const QList<QgsCoordinateReferenceSystem> filteredCrses = mModel->filteredCrs();
529 QSet<QString> ogcFilter;
530 ogcFilter.reserve( filteredCrses.size() );
539 if ( !ogcFilter.isEmpty() )
540 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
541 if ( !mMessage.isEmpty() )
542 mActivePanel->setMessage( mMessage );
543 mActivePanel->setCrs(
crs() );
545 if ( !mModel->combinedModel()->notSetText().isEmpty() )
546 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
548 mActivePanel->setPanelTitle( mDialogTitle );
552 mActivePanel->setShowNoCrs(
true );
556 if ( mIgnorePanelSignals )
559 if ( !mActivePanel->hasValidSelection() )
562 mCrsComboBox->blockSignals(
true );
564 mCrsComboBox->blockSignals(
false );
567 mIgnorePanelSignals++;
569 mIgnorePanelSignals--;
578 if ( !mMessage.isEmpty() )
580 if ( !ogcFilter.isEmpty() )
583 dlg.setWindowTitle( mDialogTitle );
585 if ( !mModel->combinedModel()->notSetText().isEmpty() )
596 mCrsComboBox->blockSignals(
true );
598 mCrsComboBox->blockSignals(
false );
605 QApplication::restoreOverrideCursor();
612 if ( !( event->possibleActions() & Qt::CopyAction ) )
618 if ( mapLayerFromMimeData( event->mimeData() ) )
621 event->setDropAction( Qt::CopyAction );
648 if ( !( event->possibleActions() & Qt::CopyAction ) )
654 if (
QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
657 setFocus( Qt::MouseFocusReason );
658 event->setDropAction( Qt::CopyAction );
661 if ( layer->crs().isValid() )
674 return mSourceEnsemble;
679 mDialogTitle = title;
689 mModel->setFilteredCrs( crses );
694 return mModel->filters();
701 mActivePanel->setFilters(
filters );
706 if ( mSourceEnsemble == ensemble )
709 mSourceEnsemble = ensemble;
715 return mShowAccuracyWarnings;
720 mShowAccuracyWarnings = show;
721 if ( !mShowAccuracyWarnings )
722 mWarningLabelContainer->hide();
727void QgsProjectionSelectionWidget::comboIndexChanged(
int idx )
729 if ( idx >= 0 && idx < mModel->rowCount() )
732 const QVariant optionData = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption );
749void QgsProjectionSelectionWidget::updateWarning()
751 if ( !mShowAccuracyWarnings )
753 if ( mWarningLabelContainer->isVisible() )
754 mWarningLabelContainer->hide();
760 const double crsAccuracyWarningThreshold =
QgsSettings().
value( QStringLiteral(
"/projections/crsAccuracyWarningThreshold" ), 0.0,
QgsSettings::App ).toDouble();
763 if ( !ensemble.
isValid() || ensemble.
name() == mSourceEnsemble || ( ensemble.
accuracy() > 0 && ensemble.
accuracy() < crsAccuracyWarningThreshold ) )
765 mWarningLabelContainer->hide();
769 mWarningLabelContainer->show();
771 QString warning = QStringLiteral(
"<p>" );
774 if ( !ensemble.
code().isEmpty() )
775 id = QStringLiteral(
"<i>%1</i> (%2:%3)" ).arg( ensemble.
name(), ensemble.
authority(), ensemble.
code() );
777 id = QStringLiteral(
"<i>%1</i>”" ).arg( ensemble.
name() );
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() );
785 warning = tr(
"The selected CRS is based on %1, which has a limited accuracy." ).arg(
id );
787 warning += QStringLiteral(
"</p><p>" ) + tr(
"Use an alternative CRS if accurate positioning is required." ) + QStringLiteral(
"</p>" );
789 const QList<QgsDatumEnsembleMember> members = ensemble.
members();
790 if ( !members.isEmpty() )
792 warning += QStringLiteral(
"<p>" ) + tr(
"%1 consists of the datums:" ).arg( ensemble.
name() ) + QStringLiteral(
"</p><ul>" );
796 if ( !member.code().isEmpty() )
797 id = QStringLiteral(
"%1 (%2:%3)" ).arg( member.name(), member.authority(), member.code() );
800 warning += QStringLiteral(
"<li>%1</li>" ).arg(
id );
803 warning += QLatin1String(
"</ul>" );
806 mWarningLabel->setToolTip( warning );
811 mWarningLabelContainer->hide();
818 mModel->setCurrentCrs(
crs );
823 mCrsComboBox->blockSignals(
true );
825 mCrsComboBox->blockSignals(
false );
830 if ( crsNotSetIndex >= 0 )
832 mCrsComboBox->blockSignals(
true );
833 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
834 mCrsComboBox->blockSignals(
false );
837 if ( mActivePanel && !mIgnorePanelSignals )
839 mIgnorePanelSignals++;
840 mActivePanel->setCrs(
crs );
841 mIgnorePanelSignals--;
843 if ( prevCrs !=
crs )
852 mModel->setLayerCrs(
crs );
860 return tr(
"invalid projection" );
863void QgsProjectionSelectionWidget::updateTooltip()
869 setToolTip( QString() );
873QgsMapLayer *QgsProjectionSelectionWidget::mapLayerFromMimeData(
const QMimeData *data )
const
@ Compound
Compound (horizontal + vertical) CRS.
@ Projected
Projected CRS.
@ DerivedProjected
Derived projected CRS.
@ Engineering
Engineering CRS.
@ Geographic3d
3D geopraphic CRS
@ Geographic2d
2D geographic CRS
@ Geocentric
Geocentric CRS.
static QString geographicCrsAuthId()
Geographic coordinate system auth:id string for a default geographic CRS (EPSG:4326).
@ 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)
@ FilterCompound
Include compound 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.
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.
Contains information about a member of a datum ensemble.
Contains information about a datum ensemble.
QString code() const
Identification code, e.g.
QString authority() const
Authority name, e.g.
bool isValid() const
Returns true if the datum ensemble is a valid object, or false if it is a null/invalid object.
QList< QgsDatumEnsembleMember > members() const
Contains a list of members of the ensemble.
QString name() const
Display name of datum ensemble.
double accuracy() const
Positional accuracy (in meters).
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.
QList< QgsMimeDataUtils::Uri > UriList
static UriList decodeUriList(const QMimeData *data)
Custom exception class which is raised when an operation is not supported.
Encapsulates a QGIS project, including sets of map layers and their styles, layouts,...
static QgsProject * instance()
Returns the QgsProject singleton instance.
void crsChanged()
Emitted when the crs() of the project has changed.
QgsCoordinateReferenceSystem crs
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
A sort/filter proxy model for recent coordinate reference systems.
Stores settings for use within QGIS.
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
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
const QgsCoordinateReferenceSystem & crs