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
67 if ( option == QgsProjectionSelectionWidget::CrsOption::Invalid )
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 ) )
296 if ( !mFilters.testFlag( QgsCoordinateReferenceSystemProxyModel::Filter::FilterHorizontal ) )
301 if ( !mFilters.testFlag( QgsCoordinateReferenceSystemProxyModel::Filter::FilterVertical ) )
306 if ( !mFilters.testFlag( QgsCoordinateReferenceSystemProxyModel::Filter::FilterCompound ) )
311 const QVariant optionInt = mModel->data( sourceIndex, StandardCoordinateReferenceSystemsModel::RoleOption );
312 if ( optionInt.isValid() )
314 if ( optionInt.toInt() > 0 )
317 if ( !mVisibleOptions.testFlag( option ) )
350 QgsProjectionSelectionWidget::CrsOption::CurrentCrs,
351 QgsProjectionSelectionWidget::CrsOption::DefaultCrs,
352 QgsProjectionSelectionWidget::CrsOption::LayerCrs,
353 QgsProjectionSelectionWidget::CrsOption::ProjectCrs
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 );
392void CombinedCoordinateReferenceSystemsProxyModel::setFilteredCrs(
const QList<QgsCoordinateReferenceSystem> &crses )
394 mFilteredCrs = crses;
400 mVisibleOptions.setFlag( option, enabled );
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 );
489 if ( !mModel->combinedModel()->currentCrs().isValid() )
503 mModel->combinedModel()->setNotSetText( text );
513 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption,
static_cast< int >( option ) );
514 return !matches.empty();
520 const QList< QgsCoordinateReferenceSystem > filteredCrses = mModel->filteredCrs();
522 QSet< QString > ogcFilter;
523 ogcFilter.reserve( filteredCrses.size( ) );
532 if ( !ogcFilter.isEmpty() )
533 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
534 if ( !mMessage.isEmpty() )
535 mActivePanel->setMessage( mMessage );
536 mActivePanel->setCrs(
crs() );
538 if ( !mModel->combinedModel()->notSetText().isEmpty() )
539 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
541 mActivePanel->setPanelTitle( mDialogTitle );
543 if (
optionVisible( QgsProjectionSelectionWidget::CrsOption::CrsNotSet ) )
545 mActivePanel->setShowNoCrs(
true );
550 if ( mIgnorePanelSignals )
553 if ( !mActivePanel->hasValidSelection() )
556 mCrsComboBox->blockSignals(
true );
558 mCrsComboBox->blockSignals(
false );
561 mIgnorePanelSignals++;
563 mIgnorePanelSignals--;
572 if ( !mMessage.isEmpty() )
574 if ( !ogcFilter.isEmpty() )
577 dlg.setWindowTitle( mDialogTitle );
579 if ( !mModel->combinedModel()->notSetText().isEmpty() )
582 if (
optionVisible( QgsProjectionSelectionWidget::CrsOption::CrsNotSet ) )
590 mCrsComboBox->blockSignals(
true );
592 mCrsComboBox->blockSignals(
false );
599 QApplication::restoreOverrideCursor();
606 if ( !( event->possibleActions() & Qt::CopyAction ) )
612 if ( mapLayerFromMimeData( event->mimeData() ) )
615 event->setDropAction( Qt::CopyAction );
642 if ( !( event->possibleActions() & Qt::CopyAction ) )
648 if (
QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
651 setFocus( Qt::MouseFocusReason );
652 event->setDropAction( Qt::CopyAction );
655 if ( layer->crs().isValid() )
668 return mSourceEnsemble;
673 mDialogTitle = title;
683 mModel->setFilteredCrs( crses );
688 return mModel->filters();
695 mActivePanel->setFilters(
filters );
700 if ( mSourceEnsemble == ensemble )
703 mSourceEnsemble = ensemble;
709 return mShowAccuracyWarnings;
714 mShowAccuracyWarnings = show;
715 if ( !mShowAccuracyWarnings )
716 mWarningLabelContainer->hide();
721void QgsProjectionSelectionWidget::comboIndexChanged(
int idx )
724 const QVariant optionData = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption );
739void QgsProjectionSelectionWidget::updateWarning()
741 if ( !mShowAccuracyWarnings )
743 if ( mWarningLabelContainer->isVisible() )
744 mWarningLabelContainer->hide();
750 const double crsAccuracyWarningThreshold =
QgsSettings().
value( QStringLiteral(
"/projections/crsAccuracyWarningThreshold" ), 0.0,
QgsSettings::App ).toDouble();
753 if ( !ensemble.
isValid() || ensemble.
name() == mSourceEnsemble || ( ensemble.
accuracy() > 0 && ensemble.
accuracy() < crsAccuracyWarningThreshold ) )
755 mWarningLabelContainer->hide();
759 mWarningLabelContainer->show();
761 QString warning = QStringLiteral(
"<p>" );
764 if ( !ensemble.
code().isEmpty() )
765 id = QStringLiteral(
"<i>%1</i> (%2:%3)" ).arg( ensemble.
name(), ensemble.
authority(), ensemble.
code() );
767 id = QStringLiteral(
"<i>%</i>”" ).arg( ensemble.
name() );
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() );
775 warning = tr(
"The selected CRS is based on %1, which has a limited accuracy." ).arg(
id );
777 warning += QStringLiteral(
"</p><p>" ) + tr(
"Use an alternative CRS if accurate positioning is required." ) + QStringLiteral(
"</p>" );
779 const QList< QgsDatumEnsembleMember > members = ensemble.
members();
780 if ( !members.isEmpty() )
782 warning += QStringLiteral(
"<p>" ) + tr(
"%1 consists of the datums:" ).arg( ensemble.
name() ) + QStringLiteral(
"</p><ul>" );
786 if ( !member.code().isEmpty() )
787 id = QStringLiteral(
"%1 (%2:%3)" ).arg( member.name(), member.authority(), member.code() );
790 warning += QStringLiteral(
"<li>%1</li>" ).arg(
id );
793 warning += QLatin1String(
"</ul>" );
796 mWarningLabel->setToolTip( warning );
801 mWarningLabelContainer->hide();
808 mModel->setCurrentCrs(
crs );
813 mCrsComboBox->blockSignals(
true );
815 mCrsComboBox->blockSignals(
false );
820 if ( crsNotSetIndex >= 0 )
822 mCrsComboBox->blockSignals(
true );
823 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
824 mCrsComboBox->blockSignals(
false );
827 if ( mActivePanel && !mIgnorePanelSignals )
829 mIgnorePanelSignals++;
830 mActivePanel->setCrs(
crs );
831 mIgnorePanelSignals--;
833 if ( prevCrs !=
crs )
842 mModel->setLayerCrs(
crs );
850 return tr(
"invalid projection" );
853void QgsProjectionSelectionWidget::updateTooltip()
859 setToolTip( QString() );
863QgsMapLayer *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...
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