28#ifdef ENABLE_MODELTEST
34StandardCoordinateReferenceSystemsModel::StandardCoordinateReferenceSystemsModel( QObject *parent )
35 : QAbstractItemModel( parent )
38#ifdef ENABLE_MODELTEST
39 new ModelTest(
this,
this );
47 mCurrentCrs.updateDefinition();
48 mLayerCrs.updateDefinition();
49 mProjectCrs.updateDefinition();
50 mDefaultCrs.updateDefinition();
54Qt::ItemFlags StandardCoordinateReferenceSystemsModel::flags(
const QModelIndex &index )
const
56 if ( !index.isValid() )
58 return Qt::ItemFlags();
61 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
64QVariant StandardCoordinateReferenceSystemsModel::data(
const QModelIndex &index,
int role )
const
97 return static_cast< int >( option );
106int StandardCoordinateReferenceSystemsModel::rowCount(
const QModelIndex &parent )
const
108 if ( parent.isValid() )
114int StandardCoordinateReferenceSystemsModel::columnCount(
const QModelIndex & )
const
119QModelIndex StandardCoordinateReferenceSystemsModel::index(
int row,
int column,
const QModelIndex &parent )
const
121 if ( row < 0 || row >= rowCount() || column != 0 || parent.isValid() )
122 return QModelIndex();
124 return createIndex( row, column );
127QModelIndex StandardCoordinateReferenceSystemsModel::parent(
const QModelIndex & )
const
129 return QModelIndex();
134 if ( !index.isValid() )
158 if ( !index.isValid() )
161 const int row = index.row();
188 return QModelIndex();
206 return index( row, 0, QModelIndex() );
213 emit dataChanged( index, index );
220 emit dataChanged( index, index );
223void StandardCoordinateReferenceSystemsModel::setNotSetText(
const QString &text )
227 emit dataChanged( index, index );
234CombinedCoordinateReferenceSystemsModel::CombinedCoordinateReferenceSystemsModel( QObject *parent )
235 : QConcatenateTablesProxyModel( parent )
236 , mStandardModel( new StandardCoordinateReferenceSystemsModel( this ) )
239 addSourceModel( mStandardModel );
240 addSourceModel( mRecentModel );
243void CombinedCoordinateReferenceSystemsModel::setNotSetText(
const QString &text )
245 mStandardModel->setNotSetText( text );
248QString CombinedCoordinateReferenceSystemsModel::notSetText()
const
250 return mStandardModel->notSetText();
255 return mStandardModel->currentCrs();
261CombinedCoordinateReferenceSystemsProxyModel::CombinedCoordinateReferenceSystemsProxyModel( QObject *parent )
262 : QSortFilterProxyModel( parent )
263 , mModel( new CombinedCoordinateReferenceSystemsModel( this ) )
269 setSourceModel( mModel );
270 setDynamicSortFilter(
true );
273bool CombinedCoordinateReferenceSystemsProxyModel::filterAcceptsRow(
int sourceRow,
const QModelIndex &sourceParent )
const
275 const QModelIndex sourceIndex = mModel->index( sourceRow, 0, sourceParent );
278 if ( !mFilteredCrs.isEmpty() && !mFilteredCrs.contains(
crs ) )
311 const QVariant optionInt = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleOption );
312 if ( optionInt.isValid() )
314 if ( optionInt.toInt() > 0 )
317 if ( !mVisibleOptions.testFlag( option ) )
356 const QModelIndexList standardItemIndex = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption,
static_cast< int >( standardOption ) );
357 if ( standardItemIndex.empty() )
360 const QgsCoordinateReferenceSystem standardItemCrs = mModel->data( standardItemIndex.at( 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value< QgsCoordinateReferenceSystem >();
361 if ( standardItemCrs ==
crs && filterAcceptsRow( standardItemIndex.at( 0 ).row(), QModelIndex() ) )
371 mModel->standardModel()->setLayerCrs(
crs );
377 mModel->standardModel()->setCurrentCrs(
crs );
381void CombinedCoordinateReferenceSystemsProxyModel::setFilters( QgsCoordinateReferenceSystemProxyModel::Filters filters )
387QgsCoordinateReferenceSystemProxyModel::Filters CombinedCoordinateReferenceSystemsProxyModel::filters()
const
392void CombinedCoordinateReferenceSystemsProxyModel::setFilteredCrs(
const QList<QgsCoordinateReferenceSystem> &crses )
394 mFilteredCrs = crses;
400 mVisibleOptions.setFlag( option, enabled );
408 QgsCoordinateReferenceSystemProxyModel::Filters filters )
410 , mDialogTitle( tr(
"Coordinate Reference System Selector" ) )
413 mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
415 mModel =
new CombinedCoordinateReferenceSystemsProxyModel(
this );
417 mCrsComboBox->setModel( mModel );
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 );
425 layout->addWidget( mCrsComboBox, 1 );
430 mWarningLabelContainer =
new QWidget();
431 QHBoxLayout *warningLayout =
new QHBoxLayout();
432 warningLayout->setContentsMargins( 0, 0, 0, 0 );
433 mWarningLabel =
new QLabel();
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();
443 layout->addSpacing( labelMargin / 2 );
445 mButton =
new QToolButton(
this );
447 mButton->setToolTip( tr(
"Select CRS" ) );
448 layout->addWidget( mButton );
450 setFocusPolicy( Qt::StrongFocus );
451 setFocusProxy( mButton );
452 setAcceptDrops(
true );
455 connect( mCrsComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsProjectionSelectionWidget::comboIndexChanged );
460 return mModel->data( mModel->index( mCrsComboBox->currentIndex(), 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<
QgsCoordinateReferenceSystem >();
472 mModel->setOption( option, visible );
488 if ( !mModel->combinedModel()->currentCrs().isValid() )
501 mModel->combinedModel()->setNotSetText( text );
511 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption,
static_cast< int >( option ) );
512 return !matches.empty();
518 const QList< QgsCoordinateReferenceSystem > filteredCrses = mModel->filteredCrs();
520 QSet< QString > ogcFilter;
521 ogcFilter.reserve( filteredCrses.size( ) );
530 if ( !ogcFilter.isEmpty() )
531 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
532 if ( !mMessage.isEmpty() )
533 mActivePanel->setMessage( mMessage );
534 mActivePanel->setCrs(
crs() );
536 if ( !mModel->combinedModel()->notSetText().isEmpty() )
537 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
539 mActivePanel->setPanelTitle( mDialogTitle );
543 mActivePanel->setShowNoCrs(
true );
548 if ( mIgnorePanelSignals )
551 if ( !mActivePanel->hasValidSelection() )
554 mCrsComboBox->blockSignals(
true );
556 mCrsComboBox->blockSignals(
false );
559 mIgnorePanelSignals++;
561 mIgnorePanelSignals--;
570 if ( !mMessage.isEmpty() )
572 if ( !ogcFilter.isEmpty() )
575 dlg.setWindowTitle( mDialogTitle );
577 if ( !mModel->combinedModel()->notSetText().isEmpty() )
588 mCrsComboBox->blockSignals(
true );
590 mCrsComboBox->blockSignals(
false );
597 QApplication::restoreOverrideCursor();
604 if ( !( event->possibleActions() & Qt::CopyAction ) )
610 if ( mapLayerFromMimeData( event->mimeData() ) )
613 event->setDropAction( Qt::CopyAction );
640 if ( !( event->possibleActions() & Qt::CopyAction ) )
646 if (
QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
649 setFocus( Qt::MouseFocusReason );
650 event->setDropAction( Qt::CopyAction );
653 if ( layer->crs().isValid() )
666 return mSourceEnsemble;
671 mDialogTitle = title;
681 mModel->setFilteredCrs( crses );
686 return mModel->filters();
693 mActivePanel->setFilters(
filters );
698 if ( mSourceEnsemble == ensemble )
701 mSourceEnsemble = ensemble;
707 return mShowAccuracyWarnings;
712 mShowAccuracyWarnings = show;
713 if ( !mShowAccuracyWarnings )
714 mWarningLabelContainer->hide();
719void QgsProjectionSelectionWidget::comboIndexChanged(
int idx )
722 switch (
static_cast< CrsOption >( mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption ).toInt() ) )
741void QgsProjectionSelectionWidget::updateWarning()
743 if ( !mShowAccuracyWarnings )
745 if ( mWarningLabelContainer->isVisible() )
746 mWarningLabelContainer->hide();
752 const double crsAccuracyWarningThreshold =
QgsSettings().
value( QStringLiteral(
"/projections/crsAccuracyWarningThreshold" ), 0.0,
QgsSettings::App ).toDouble();
755 if ( !ensemble.
isValid() || ensemble.
name() == mSourceEnsemble || ( ensemble.
accuracy() > 0 && ensemble.
accuracy() < crsAccuracyWarningThreshold ) )
757 mWarningLabelContainer->hide();
761 mWarningLabelContainer->show();
763 QString warning = QStringLiteral(
"<p>" );
766 if ( !ensemble.
code().isEmpty() )
767 id = QStringLiteral(
"<i>%1</i> (%2:%3)" ).arg( ensemble.
name(), ensemble.
authority(), ensemble.
code() );
769 id = QStringLiteral(
"<i>%</i>”" ).arg( ensemble.
name() );
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() );
777 warning = tr(
"The selected CRS is based on %1, which has a limited accuracy." ).arg(
id );
779 warning += QStringLiteral(
"</p><p>" ) + tr(
"Use an alternative CRS if accurate positioning is required." ) + QStringLiteral(
"</p>" );
781 const QList< QgsDatumEnsembleMember > members = ensemble.
members();
782 if ( !members.isEmpty() )
784 warning += QStringLiteral(
"<p>" ) + tr(
"%1 consists of the datums:" ).arg( ensemble.
name() ) + QStringLiteral(
"</p><ul>" );
788 if ( !member.code().isEmpty() )
789 id = QStringLiteral(
"%1 (%2:%3)" ).arg( member.name(), member.authority(), member.code() );
792 warning += QStringLiteral(
"<li>%1</li>" ).arg(
id );
795 warning += QLatin1String(
"</ul>" );
798 mWarningLabel->setToolTip( warning );
803 mWarningLabelContainer->hide();
810 mModel->setCurrentCrs(
crs );
815 mCrsComboBox->blockSignals(
true );
817 mCrsComboBox->blockSignals(
false );
822 if ( crsNotSetIndex >= 0 )
824 mCrsComboBox->blockSignals(
true );
825 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
826 mCrsComboBox->blockSignals(
false );
829 if ( mActivePanel && !mIgnorePanelSignals )
831 mIgnorePanelSignals++;
832 mActivePanel->setCrs(
crs );
833 mIgnorePanelSignals--;
835 if ( prevCrs !=
crs )
844 mModel->setLayerCrs(
crs );
852 return tr(
"invalid projection" );
855void QgsProjectionSelectionWidget::updateTooltip()
861 setToolTip( QString() );
865QgsMapLayer *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.
@ 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.
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.
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,...
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.
This class is a composition of two QSettings instances:
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.
CONSTLATIN1STRING geoEpsgCrsAuthId()
Geographic coord sys from EPSG authority.
const QgsCoordinateReferenceSystem & crs