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();
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 );
409 , mDialogTitle( tr(
"Coordinate Reference System Selector" ) )
412 mCrsComboBox->setSizePolicy( QSizePolicy::Ignored, QSizePolicy::Preferred );
414 mModel =
new CombinedCoordinateReferenceSystemsProxyModel(
this );
416 mCrsComboBox->setModel( mModel );
418 const int labelMargin =
static_cast<int>( std::round( mCrsComboBox->fontMetrics().horizontalAdvance(
'X' ) ) );
419 QHBoxLayout *layout =
new QHBoxLayout();
420 layout->setContentsMargins( 0, 0, 0, 0 );
421 layout->setSpacing( 0 );
424 layout->addWidget( mCrsComboBox, 1 );
429 mWarningLabelContainer =
new QWidget();
430 QHBoxLayout *warningLayout =
new QHBoxLayout();
431 warningLayout->setContentsMargins( 0, 0, 0, 0 );
432 mWarningLabel =
new QLabel();
434 const int size =
static_cast<int>( std::max( 24.0, mCrsComboBox->minimumSize().height() * 0.5 ) );
435 mWarningLabel->setPixmap( icon.pixmap( icon.actualSize( QSize( size, size ) ) ) );
436 warningLayout->insertSpacing( 0, labelMargin / 2 );
437 warningLayout->insertWidget( 1, mWarningLabel );
438 mWarningLabelContainer->setLayout( warningLayout );
439 layout->addWidget( mWarningLabelContainer );
440 mWarningLabelContainer->hide();
442 layout->addSpacing( labelMargin / 2 );
444 mButton =
new QToolButton(
this );
446 mButton->setToolTip( tr(
"Select CRS" ) );
447 layout->addWidget( mButton );
449 setFocusPolicy( Qt::StrongFocus );
450 setFocusProxy( mButton );
451 setAcceptDrops(
true );
454 connect( mCrsComboBox,
static_cast<void ( QComboBox::* )(
int )
>( &QComboBox::currentIndexChanged ),
this, &QgsProjectionSelectionWidget::comboIndexChanged );
459 const int idx = mCrsComboBox->currentIndex();
460 if ( idx >= 0 && idx < mModel->rowCount() )
475 mModel->setOption( option, visible );
492 if ( !mModel->combinedModel()->currentCrs().isValid() )
506 mModel->combinedModel()->setNotSetText( text );
516 const QModelIndexList matches = mModel->match( mModel->index( 0, 0 ), StandardCoordinateReferenceSystemsModel::Role::RoleOption,
static_cast<int>( option ) );
517 return !matches.empty();
523 const QList<QgsCoordinateReferenceSystem> filteredCrses = mModel->filteredCrs();
525 QSet<QString> ogcFilter;
526 ogcFilter.reserve( filteredCrses.size() );
535 if ( !ogcFilter.isEmpty() )
536 mActivePanel->setOgcWmsCrsFilter( ogcFilter );
537 if ( !mMessage.isEmpty() )
538 mActivePanel->setMessage( mMessage );
539 mActivePanel->setCrs(
crs() );
541 if ( !mModel->combinedModel()->notSetText().isEmpty() )
542 mActivePanel->setNotSetText( mModel->combinedModel()->notSetText() );
544 mActivePanel->setPanelTitle( mDialogTitle );
548 mActivePanel->setShowNoCrs(
true );
552 if ( mIgnorePanelSignals )
555 if ( !mActivePanel->hasValidSelection() )
558 mCrsComboBox->blockSignals(
true );
560 mCrsComboBox->blockSignals(
false );
563 mIgnorePanelSignals++;
565 mIgnorePanelSignals--;
574 if ( !mMessage.isEmpty() )
576 if ( !ogcFilter.isEmpty() )
579 dlg.setWindowTitle( mDialogTitle );
581 if ( !mModel->combinedModel()->notSetText().isEmpty() )
592 mCrsComboBox->blockSignals(
true );
594 mCrsComboBox->blockSignals(
false );
601 QApplication::restoreOverrideCursor();
608 if ( !( event->possibleActions() & Qt::CopyAction ) )
614 if ( mapLayerFromMimeData( event->mimeData() ) )
617 event->setDropAction( Qt::CopyAction );
644 if ( !( event->possibleActions() & Qt::CopyAction ) )
650 if (
QgsMapLayer *layer = mapLayerFromMimeData( event->mimeData() ) )
653 setFocus( Qt::MouseFocusReason );
654 event->setDropAction( Qt::CopyAction );
657 if ( layer->crs().isValid() )
670 return mSourceEnsemble;
675 mDialogTitle = title;
685 mModel->setFilteredCrs( crses );
690 return mModel->filters();
697 mActivePanel->setFilters(
filters );
702 if ( mSourceEnsemble == ensemble )
705 mSourceEnsemble = ensemble;
711 return mShowAccuracyWarnings;
716 mShowAccuracyWarnings = show;
717 if ( !mShowAccuracyWarnings )
718 mWarningLabelContainer->hide();
723void QgsProjectionSelectionWidget::comboIndexChanged(
int idx )
725 if ( idx >= 0 && idx < mModel->rowCount() )
728 const QVariant optionData = mModel->data( mModel->index( idx, 0 ), StandardCoordinateReferenceSystemsModel::RoleOption );
745void QgsProjectionSelectionWidget::updateWarning()
747 if ( !mShowAccuracyWarnings )
749 if ( mWarningLabelContainer->isVisible() )
750 mWarningLabelContainer->hide();
756 const double crsAccuracyWarningThreshold =
QgsSettings().
value( QStringLiteral(
"/projections/crsAccuracyWarningThreshold" ), 0.0,
QgsSettings::App ).toDouble();
759 if ( !ensemble.
isValid() || ensemble.
name() == mSourceEnsemble || ( ensemble.
accuracy() > 0 && ensemble.
accuracy() < crsAccuracyWarningThreshold ) )
761 mWarningLabelContainer->hide();
765 mWarningLabelContainer->show();
767 QString warning = QStringLiteral(
"<p>" );
770 if ( !ensemble.
code().isEmpty() )
771 id = QStringLiteral(
"<i>%1</i> (%2:%3)" ).arg( ensemble.
name(), ensemble.
authority(), ensemble.
code() );
773 id = QStringLiteral(
"<i>%</i>”" ).arg( ensemble.
name() );
777 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() );
781 warning = tr(
"The selected CRS is based on %1, which has a limited accuracy." ).arg(
id );
783 warning += QStringLiteral(
"</p><p>" ) + tr(
"Use an alternative CRS if accurate positioning is required." ) + QStringLiteral(
"</p>" );
785 const QList<QgsDatumEnsembleMember> members = ensemble.
members();
786 if ( !members.isEmpty() )
788 warning += QStringLiteral(
"<p>" ) + tr(
"%1 consists of the datums:" ).arg( ensemble.
name() ) + QStringLiteral(
"</p><ul>" );
792 if ( !member.code().isEmpty() )
793 id = QStringLiteral(
"%1 (%2:%3)" ).arg( member.name(), member.authority(), member.code() );
796 warning += QStringLiteral(
"<li>%1</li>" ).arg(
id );
799 warning += QLatin1String(
"</ul>" );
802 mWarningLabel->setToolTip( warning );
807 mWarningLabelContainer->hide();
814 mModel->setCurrentCrs(
crs );
819 mCrsComboBox->blockSignals(
true );
821 mCrsComboBox->blockSignals(
false );
826 if ( crsNotSetIndex >= 0 )
828 mCrsComboBox->blockSignals(
true );
829 mCrsComboBox->setCurrentIndex( crsNotSetIndex );
830 mCrsComboBox->blockSignals(
false );
833 if ( mActivePanel && !mIgnorePanelSignals )
835 mIgnorePanelSignals++;
836 mActivePanel->setCrs(
crs );
837 mIgnorePanelSignals--;
839 if ( prevCrs !=
crs )
848 mModel->setLayerCrs(
crs );
856 return tr(
"invalid projection" );
859void QgsProjectionSelectionWidget::updateTooltip()
865 setToolTip( QString() );
869QgsMapLayer *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