20 #include <QMessageBox>
21 #include <QRegularExpression>
22 #include <QRegularExpressionMatch>
30 connect( mButtonCalculate, &QPushButton::clicked,
this, &QgsCrsDefinitionWidget::pbnCalculate_clicked );
31 connect( mButtonCopyCRS, &QPushButton::clicked,
this, &QgsCrsDefinitionWidget::pbnCopyCRS_clicked );
32 connect( mButtonValidate, &QPushButton::clicked,
this, &QgsCrsDefinitionWidget::validateCurrent );
34 mFormatComboBox->addItem( tr(
"WKT (Recommended)" ),
static_cast< int >( Qgis::CrsDefinitionFormat::Wkt ) );
35 mFormatComboBox->addItem( tr(
"Proj String (Legacy — Not Recommended)" ),
static_cast< int >( Qgis::CrsDefinitionFormat::Proj ) );
36 mFormatComboBox->setCurrentIndex( mFormatComboBox->findData(
static_cast< int >( Qgis::CrsDefinitionFormat::Wkt ) ) );
38 connect( mFormatComboBox, qOverload<int>( &QComboBox::currentIndexChanged ),
this, &QgsCrsDefinitionWidget::formatChanged );
47 case Qgis::CrsDefinitionFormat::Wkt:
51 case Qgis::CrsDefinitionFormat::Proj:
67 switch ( nativeFormat )
69 case Qgis::CrsDefinitionFormat::Wkt:
72 case Qgis::CrsDefinitionFormat::Proj:
77 whileBlocking( mFormatComboBox )->setCurrentIndex( mFormatComboBox->findData(
static_cast< int >( nativeFormat ) ) );
88 mFormatComboBox->setCurrentIndex( mFormatComboBox->findData(
static_cast< int >(
format ) ) );
93 return mTextEditParameters->toPlainText();
98 mTextEditParameters->setPlainText( definition );
101 void QgsCrsDefinitionWidget::pbnCopyCRS_clicked()
103 std::unique_ptr< QgsProjectionSelectionDialog > selector = std::make_unique< QgsProjectionSelectionDialog >(
this );
104 if ( selector->exec() )
108 whileBlocking( mFormatComboBox )->setCurrentIndex( mFormatComboBox->findData(
static_cast< int >( Qgis::CrsDefinitionFormat::Wkt ) ) );
113 static void proj_collecting_logger(
void *user_data,
int ,
const char *message )
115 QStringList *dest =
reinterpret_cast< QStringList *
>( user_data );
116 QString messageString( message );
117 messageString.replace( QLatin1String(
"internal_proj_create: " ), QString() );
118 dest->append( messageString );
121 void QgsCrsDefinitionWidget::validateCurrent()
123 const QString projDef = mTextEditParameters->toPlainText();
127 QStringList projErrors;
128 proj_log_func( context, &projErrors, proj_collecting_logger );
133 case Qgis::CrsDefinitionFormat::Wkt:
135 PROJ_STRING_LIST warnings =
nullptr;
136 PROJ_STRING_LIST grammerErrors =
nullptr;
137 crs.reset( proj_create_from_wkt( context, projDef.toUtf8().constData(),
nullptr, &warnings, &grammerErrors ) );
138 QStringList warningStrings;
139 QStringList grammerStrings;
140 for (
auto iter = warnings; iter && *iter; ++iter )
141 warningStrings << QString( *iter );
142 for (
auto iter = grammerErrors; iter && *iter; ++iter )
143 grammerStrings << QString( *iter );
144 proj_string_list_destroy( warnings );
145 proj_string_list_destroy( grammerErrors );
149 QMessageBox::information(
this, tr(
"Custom Coordinate Reference System" ),
150 tr(
"This WKT projection definition is valid." ) );
154 QMessageBox::warning(
this, tr(
"Custom Coordinate Reference System" ),
155 tr(
"This WKT projection definition is not valid:" ) + QStringLiteral(
"\n\n" ) + warningStrings.join(
'\n' ) + grammerStrings.join(
'\n' ) );
160 case Qgis::CrsDefinitionFormat::Proj:
162 const QString projCrsString = projDef + ( projDef.contains( QStringLiteral(
"+type=crs" ) ) ? QString() : QStringLiteral(
" +type=crs" ) );
163 crs.reset( proj_create( context, projCrsString.toUtf8().constData() ) );
166 QMessageBox::information(
this, tr(
"Custom Coordinate Reference System" ),
167 tr(
"This proj projection definition is valid." ) );
171 QMessageBox::warning(
this, tr(
"Custom Coordinate Reference System" ),
172 tr(
"This proj projection definition is not valid:" ) + QStringLiteral(
"\n\n" ) + projErrors.join(
'\n' ) );
179 proj_log_func( context,
nullptr,
nullptr );
180 proj_context_destroy( context );
184 void QgsCrsDefinitionWidget::formatChanged()
187 QString newFormatString;
190 case Qgis::CrsDefinitionFormat::Proj:
192 crs.
createFromWkt( multiLineWktToSingleLine( mTextEditParameters->toPlainText() ) );
198 case Qgis::CrsDefinitionFormat::Wkt:
201 QString proj = mTextEditParameters->toPlainText();
202 proj.replace( QLatin1String(
"+type=crs" ), QString() );
203 proj += QLatin1String(
" +type=crs" );
207 const QByteArray multiLineOption = QStringLiteral(
"MULTILINE=YES" ).toLocal8Bit();
208 const char *
const options[] = {multiLineOption.constData(),
nullptr};
209 newFormatString = QString( proj_as_wkt( pjContext,
crs.get(), PJ_WKT2_2019, options ) );
214 if ( !newFormatString.isEmpty() )
215 mTextEditParameters->setPlainText( newFormatString );
218 void QgsCrsDefinitionWidget::pbnCalculate_clicked()
221 QString projDef = mTextEditParameters->toPlainText();
225 double latitude = mNorthWGS84Edit->text().toDouble( &okN );
226 double longitude = mEastWGS84Edit->text().toDouble( &okE );
230 QMessageBox::warning(
this, tr(
"Custom Coordinate Reference System" ),
231 tr(
"Latitude and Longitude must be in decimal form." ) );
232 mProjectedXLabel->clear();
233 mProjectedYLabel->clear();
238 if (
static_cast< Qgis::CrsDefinitionFormat >( mFormatComboBox->currentData().toInt() ) == Qgis::CrsDefinitionFormat::Proj )
240 projDef = projDef + ( projDef.contains( QStringLiteral(
"+type=crs" ) ) ? QString() : QStringLiteral(
" +type=crs" ) );
250 QMessageBox::warning(
this, tr(
"Custom Coordinate Reference System" ),
251 tr(
"This CRS projection definition is not valid." ) );
252 mProjectedXLabel->clear();
253 mProjectedYLabel->clear();
262 mProjectedXLabel->setText( QLocale().toString( res.
x(),
'f',
precision ) );
263 mProjectedYLabel->setText( QLocale().toString( res.
y(),
'f',
precision ) );
267 mProjectedXLabel->setText( tr(
"Error" ) );
268 mProjectedYLabel->setText( tr(
"Error" ) );
269 QMessageBox::warning(
this, tr(
"Custom Coordinate Reference System" ),
274 QString QgsCrsDefinitionWidget::multiLineWktToSingleLine(
const QString &wkt )
277 QRegularExpression re( QStringLiteral(
"\\s*\\n\\s*" ) );
278 re.setPatternOptions( QRegularExpression::MultilineOption );
279 res.replace( re, QString() );
CrsDefinitionFormat
CRS definition formats.
This class represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromWkt(const QString &wkt)
Sets this CRS using a WKT definition.
QString toProj() const
Returns a Proj string representation of this CRS.
Qgis::CrsDefinitionFormat nativeFormat() const
Returns the native format for the CRS definition.
void setNativeFormat(Qgis::CrsDefinitionFormat format)
Sets the native format for the CRS definition.
QgsCoordinateReferenceSystem toGeographicCrs() const
Returns the geographic CRS associated with this CRS object.
static QgsCoordinateReferenceSystem fromProj(const QString &proj)
Creates a CRS from a proj style formatted string.
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
static QgsCoordinateReferenceSystem fromWkt(const QString &wkt)
Creates a CRS from a WKT spatial ref sys definition string.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Contains information about the context in which a coordinate transform is executed.
Custom exception class for Coordinate Reference System related exceptions.
A class to represent a 2D point.
static PJ_CONTEXT * get()
Returns a thread local instance of a proj context, safe for use in the current thread.
std::unique_ptr< PJ, ProjPJDeleter > proj_pj_unique_ptr
Scoped Proj PJ object.
QgsSignalBlocker< Object > whileBlocking(Object *object)
Temporarily blocks signals from a QObject while calling a single method from the object.
struct projCtx_t PJ_CONTEXT
const QgsCoordinateReferenceSystem & crs