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 );
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 const int idx = mCrsComboBox->currentIndex();
461 if ( idx >= 0 && idx < mModel->rowCount() )
462 return mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleCrs ).value<
QgsCoordinateReferenceSystem >();
476 mModel->setOption( option, visible );
493 if ( !mModel->combinedModel()->currentCrs().isValid() )
507 mModel->combinedModel()->setNotSetText( text );
517 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption,
static_cast< int >( option ) );
518 return !matches.empty();
524 const QList< QgsCoordinateReferenceSystem > filteredCrses = mModel->filteredCrs();
526 QSet< QString > ogcFilter;
527 ogcFilter.reserve( filteredCrses.size( ) );
536 if ( !ogcFilter.isEmpty() )
537 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
538 if ( !mMessage.isEmpty() )
539 mActivePanel->setMessage( mMessage );
540 mActivePanel->setCrs(
crs() );
542 if ( !mModel->combinedModel()->notSetText().isEmpty() )
543 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
545 mActivePanel->setPanelTitle( mDialogTitle );
549 mActivePanel->setShowNoCrs(
true );
554 if ( mIgnorePanelSignals )
557 if ( !mActivePanel->hasValidSelection() )
560 mCrsComboBox->blockSignals(
true );
562 mCrsComboBox->blockSignals(
false );
565 mIgnorePanelSignals++;
567 mIgnorePanelSignals--;
576 if ( !mMessage.isEmpty() )
578 if ( !ogcFilter.isEmpty() )
581 dlg.setWindowTitle( mDialogTitle );
583 if ( !mModel->combinedModel()->notSetText().isEmpty() )
594 mCrsComboBox->blockSignals(
true );
596 mCrsComboBox->blockSignals(
false );
603 QApplication::restoreOverrideCursor();
610 if ( !( event->possibleActions() & Qt::CopyAction ) )
616 if ( mapLayerFromMimeData( event->mimeData() ) )
619 event->setDropAction( Qt::CopyAction );
646 if ( !( event->possibleActions() & Qt::CopyAction ) )
652 if (
QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
655 setFocus( Qt::MouseFocusReason );
656 event->setDropAction( Qt::CopyAction );
659 if ( layer->crs().isValid() )
672 return mSourceEnsemble;
677 mDialogTitle = title;
687 mModel->setFilteredCrs( crses );
692 return mModel->filters();
699 mActivePanel->setFilters(
filters );
704 if ( mSourceEnsemble == ensemble )
707 mSourceEnsemble = ensemble;
713 return mShowAccuracyWarnings;
718 mShowAccuracyWarnings = show;
719 if ( !mShowAccuracyWarnings )
720 mWarningLabelContainer->hide();
725void QgsProjectionSelectionWidget::comboIndexChanged(
int idx )
727 if ( idx >= 0 && idx < mModel->rowCount() )
730 const QVariant optionData = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption );
747void QgsProjectionSelectionWidget::updateWarning()
749 if ( !mShowAccuracyWarnings )
751 if ( mWarningLabelContainer->isVisible() )
752 mWarningLabelContainer->hide();
758 const double crsAccuracyWarningThreshold =
QgsSettings().
value( QStringLiteral(
"/projections/crsAccuracyWarningThreshold" ), 0.0,
QgsSettings::App ).toDouble();
761 if ( !ensemble.
isValid() || ensemble.
name() == mSourceEnsemble || ( ensemble.
accuracy() > 0 && ensemble.
accuracy() < crsAccuracyWarningThreshold ) )
763 mWarningLabelContainer->hide();
767 mWarningLabelContainer->show();
769 QString warning = QStringLiteral(
"<p>" );
772 if ( !ensemble.
code().isEmpty() )
773 id = QStringLiteral(
"<i>%1</i> (%2:%3)" ).arg( ensemble.
name(), ensemble.
authority(), ensemble.
code() );
775 id = QStringLiteral(
"<i>%</i>”" ).arg( ensemble.
name() );
779 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() );
783 warning = tr(
"The selected CRS is based on %1, which has a limited accuracy." ).arg(
id );
785 warning += QStringLiteral(
"</p><p>" ) + tr(
"Use an alternative CRS if accurate positioning is required." ) + QStringLiteral(
"</p>" );
787 const QList< QgsDatumEnsembleMember > members = ensemble.
members();
788 if ( !members.isEmpty() )
790 warning += QStringLiteral(
"<p>" ) + tr(
"%1 consists of the datums:" ).arg( ensemble.
name() ) + QStringLiteral(
"</p><ul>" );
794 if ( !member.code().isEmpty() )
795 id = QStringLiteral(
"%1 (%2:%3)" ).arg( member.name(), member.authority(), member.code() );
798 warning += QStringLiteral(
"<li>%1</li>" ).arg(
id );
801 warning += QLatin1String(
"</ul>" );
804 mWarningLabel->setToolTip( warning );
809 mWarningLabelContainer->hide();
816 mModel->setCurrentCrs(
crs );
821 mCrsComboBox->blockSignals(
true );
823 mCrsComboBox->blockSignals(
false );
828 if ( crsNotSetIndex >= 0 )
830 mCrsComboBox->blockSignals(
true );
831 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
832 mCrsComboBox->blockSignals(
false );
835 if ( mActivePanel && !mIgnorePanelSignals )
837 mIgnorePanelSignals++;
838 mActivePanel->setCrs(
crs );
839 mIgnorePanelSignals--;
841 if ( prevCrs !=
crs )
850 mModel->setLayerCrs(
crs );
858 return tr(
"invalid projection" );
861void QgsProjectionSelectionWidget::updateTooltip()
867 setToolTip( QString() );
871QgsMapLayer *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