QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgscoordinatenumericformat.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgscoordinatenumericformat.cpp
3 --------------------------
4 begin : April 2022
5 copyright : (C) 2022 by Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
17
18#include <iomanip>
19#include <iostream>
20#include <locale>
21#include <memory>
22
23#include "qgis.h"
25
26#include <QString>
27
28#include "moc_qgscoordinatenumericformat.cpp"
29
30using namespace Qt::StringLiterals;
31
33namespace QgsGeographicCoordinateNumericFormat_ns
34{
35 struct formatter : std::numpunct<wchar_t>
36 {
37 formatter( QChar thousands, bool showThousands, QChar decimal )
38 : mThousands( thousands.unicode() )
39 , mDecimal( decimal.unicode() )
40 , mShowThousands( showThousands )
41 {}
42 wchar_t do_decimal_point() const override { return mDecimal; }
43 wchar_t do_thousands_sep() const override { return mThousands; }
44 std::string do_grouping() const override { return mShowThousands ? "\3" : "\0"; }
45
46 wchar_t mThousands;
47 wchar_t mDecimal;
48 bool mShowThousands = true;
49 };
50}
52
56
58{
59 return u"geographiccoordinate"_s;
60}
61
63{
64 return QObject::tr( "Geographic Coordinate" );
65}
66
71
73{
74 return 3.7555;
75}
76
78{
79 const QChar decimal = decimalSeparator().isNull() ? context.decimalSeparator() : decimalSeparator();
80 std::basic_stringstream<wchar_t> os;
81 os.imbue( std::locale( os.getloc(), new QgsGeographicCoordinateNumericFormat_ns::formatter( thousandsSeparator().isNull() ? context.thousandsSeparator() : thousandsSeparator(),
82 false,
83 decimal ) ) );
84
85 switch ( context.interpretation() )
86 {
88 return formatLatitude( value, os, context );
89
92 return formatLongitude( value, os, context );
93 }
95}
96
101
103{
104 auto res = std::make_unique< QgsGeographicCoordinateNumericFormat >();
105 res->setConfiguration( configuration, context );
106 res->mAngleFormat = qgsEnumKeyToValue( configuration.value( u"angle_format"_s ).toString(), AngleFormat::DecimalDegrees );
107 res->mShowLeadingZeros = configuration.value( u"show_leading_zeros"_s, false ).toBool();
108 res->mShowLeadingDegreeZeros = configuration.value( u"show_leading_degree_zeros"_s, false ).toBool();
109 res->mUseSuffix = configuration.value( u"show_suffix"_s, false ).toBool();
110 return res.release();
111}
112
114{
115 QVariantMap res = QgsBasicNumericFormat::configuration( context );
116 res.insert( u"angle_format"_s, qgsEnumValueToKey( mAngleFormat ) );
117 res.insert( u"show_leading_zeros"_s, mShowLeadingZeros );
118 res.insert( u"show_leading_degree_zeros"_s, mShowLeadingDegreeZeros );
119 res.insert( u"show_suffix"_s, mUseSuffix );
120 return res;
121}
122
127
132
134{
136 mAngleFormat = qgsEnumKeyToValue( configuration.value( u"angle_format"_s ).toString(), AngleFormat::DecimalDegrees );
137 mShowLeadingZeros = configuration.value( u"show_leading_zeros"_s, false ).toBool();
138 mShowLeadingDegreeZeros = configuration.value( u"show_leading_degree_zeros"_s, false ).toBool();
139 mUseSuffix = configuration.value( u"show_suffix"_s, false ).toBool();
140}
141
143{
144 return mShowLeadingZeros;
145}
146
148{
149 mShowLeadingZeros = newShowLeadingZeros;
150}
151
153{
154 return mShowLeadingDegreeZeros;
155}
156
158{
159 mShowLeadingDegreeZeros = show;
160}
161
163{
164 return mUseSuffix;
165}
166
168{
169 mUseSuffix = show;
170}
171
172QString QgsGeographicCoordinateNumericFormat::formatLongitude( double value, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
173{
174 switch ( mAngleFormat )
175 {
177 return formatLongitudeAsDegreesMinutesSeconds( value, ss, context );
179 return formatLongitudeAsDegreesMinutes( value, ss, context );
181 return formatLongitudeAsDegrees( value, ss, context );
182 }
184}
185
186QString QgsGeographicCoordinateNumericFormat::formatLatitude( double value, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
187{
188 switch ( mAngleFormat )
189 {
191 return formatLatitudeAsDegreesMinutesSeconds( value, ss, context );
193 return formatLatitudeAsDegreesMinutes( value, ss, context );
195 return formatLatitudeAsDegrees( value, ss, context );
196 }
198}
199
200QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutesSeconds( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
201{
202 //first, limit latitude to -180 to 180 degree range
203 double wrappedY = std::fmod( val, 180.0 );
204 //next, wrap around latitudes > 90 or < -90 degrees, so that eg "110S" -> "70N"
205 if ( wrappedY > 90.0 )
206 {
207 wrappedY = wrappedY - 180.0;
208 }
209 else if ( wrappedY < -90.0 )
210 {
211 wrappedY = wrappedY + 180.0;
212 }
213
214 const double precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
215
216 int degreesY = int( std::fabs( wrappedY ) );
217 const double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
218 int intMinutesY = int( floatMinutesY );
219 double secondsY = ( floatMinutesY - intMinutesY ) * 60.0;
220
221 //make sure rounding to specified precision doesn't create seconds >= 60
222 if ( std::round( secondsY * precisionMultiplier ) >= 60 * precisionMultiplier )
223 {
224 secondsY = std::max( secondsY - 60, 0.0 );
225 intMinutesY++;
226 if ( intMinutesY >= 60 )
227 {
228 intMinutesY -= 60;
229 degreesY++;
230 }
231 }
232
233 QString hemisphere;
234 QString sign;
235 if ( mUseSuffix )
236 {
237 hemisphere = wrappedY < 0 ? QObject::tr( "S" ) : QObject::tr( "N" );
238 }
239 else
240 {
241 if ( wrappedY < 0 )
242 {
243 sign = context.negativeSign();
244 }
245 }
246 //check if coordinate is all zeros for the specified precision, and if so,
247 //remove the sign and hemisphere strings
248 if ( degreesY == 0 && intMinutesY == 0 && std::round( secondsY * precisionMultiplier ) == 0 )
249 {
250 sign = QString();
251 hemisphere.clear();
252 }
253
254 QString strMinutesY;
255 QString strSecondsY;
256
257 ss << std::fixed << std::setprecision( 0 );
258 ss << intMinutesY;
259
260 strMinutesY = QString::fromStdWString( ss.str() );
261 ss.str( std::wstring() );
262
263 ss << std::fixed << std::setprecision( numberDecimalPlaces() );
264 ss << secondsY;
265 strSecondsY = QString::fromStdWString( ss.str() );
266 ss.str( std::wstring() );
267
268 trimTrailingZeros( strSecondsY, context );
269
270 //pad with leading digits if required
271 if ( mShowLeadingZeros && intMinutesY < 10 )
272 strMinutesY = '0' + strMinutesY;
273
274 if ( mShowLeadingZeros && secondsY < 10 )
275 strSecondsY = '0' + strSecondsY;
276
277 ss << std::fixed << std::setprecision( 0 );
278 ss << degreesY;
279 QString degreesYStr = QString::fromStdWString( ss.str() );
280 ss.str( std::wstring() );
281
282 if ( mShowLeadingDegreeZeros )
283 degreesYStr = QString( u"00"_s + degreesYStr ).right( 2 );
284
285 return sign + degreesYStr + QChar( 176 ) +
286 strMinutesY + QChar( 0x2032 ) +
287 strSecondsY + QChar( 0x2033 ) +
288 hemisphere;
289}
290
291QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutesSeconds( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
292{
293 //first, limit longitude to -360 to 360 degree range
294 double wrappedX = std::fmod( val, 360.0 );
295 //next, wrap around longitudes > 180 or < -180 degrees, so that eg "190E" -> "170W"
296 if ( wrappedX > 180.0 )
297 {
298 wrappedX = wrappedX - 360.0;
299 }
300 else if ( wrappedX < -180.0 )
301 {
302 wrappedX = wrappedX + 360.0;
303 }
304
305 const double precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
306
307 int degreesX = int( std::fabs( wrappedX ) );
308 const double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
309 int intMinutesX = int( floatMinutesX );
310 double secondsX = ( floatMinutesX - intMinutesX ) * 60.0;
311
312 //make sure rounding to specified precision doesn't create seconds >= 60
313 if ( std::round( secondsX * precisionMultiplier ) >= 60 * precisionMultiplier )
314 {
315 secondsX = std::max( secondsX - 60, 0.0 );
316 intMinutesX++;
317 if ( intMinutesX >= 60 )
318 {
319 intMinutesX -= 60;
320 degreesX++;
321 }
322 }
323
324 QString hemisphere;
325 QString sign;
326 if ( mUseSuffix )
327 {
328 hemisphere = wrappedX < 0 ? QObject::tr( "W" ) : QObject::tr( "E" );
329 }
330 else
331 {
332 if ( wrappedX < 0 )
333 {
334 sign = context.negativeSign();
335 }
336 }
337 //check if coordinate is all zeros for the specified precision, and if so,
338 //remove the sign and hemisphere strings
339 if ( degreesX == 0 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
340 {
341 sign.clear();
342 hemisphere.clear();
343 }
344
345 //also remove directional prefix from 180 degree longitudes
346 if ( degreesX == 180 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
347 {
348 hemisphere.clear();
349 }
350
351 QString minutesX;
352 QString strSecondsX;
353
354 ss << std::fixed << std::setprecision( 0 );
355 ss << intMinutesX;
356
357 minutesX = QString::fromStdWString( ss.str() );
358 ss.str( std::wstring() );
359
360 ss << std::fixed << std::setprecision( numberDecimalPlaces() );
361 ss << secondsX;
362 strSecondsX = QString::fromStdWString( ss.str() );
363 ss.str( std::wstring() );
364
365 trimTrailingZeros( strSecondsX, context );
366
367 //pad with leading digits if required
368 if ( mShowLeadingZeros && intMinutesX < 10 )
369 minutesX = '0' + minutesX;
370
371 if ( mShowLeadingZeros && secondsX < 10 )
372 strSecondsX = '0' + strSecondsX;
373
374 ss << std::fixed << std::setprecision( 0 );
375 ss << degreesX;
376 QString degreesXStr = QString::fromStdWString( ss.str() );
377 ss.str( std::wstring() );
378
379 if ( mShowLeadingDegreeZeros )
380 degreesXStr = QString( u"000"_s + degreesXStr ).right( 3 );
381
382 return sign + degreesXStr + QChar( 176 ) +
383 minutesX + QChar( 0x2032 ) +
384 strSecondsX + QChar( 0x2033 ) +
385 hemisphere;
386}
387
388QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutes( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
389{
390 //first, limit latitude to -180 to 180 degree range
391 double wrappedY = std::fmod( val, 180.0 );
392 //next, wrap around latitudes > 90 or < -90 degrees, so that eg "110S" -> "70N"
393 if ( wrappedY > 90.0 )
394 {
395 wrappedY = wrappedY - 180.0;
396 }
397 else if ( wrappedY < -90.0 )
398 {
399 wrappedY = wrappedY + 180.0;
400 }
401
402 int degreesY = int( std::fabs( wrappedY ) );
403 double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
404
405 const double precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
406
407 //make sure rounding to specified precision doesn't create minutes >= 60
408 if ( std::round( floatMinutesY * precisionMultiplier ) >= 60 * precisionMultiplier )
409 {
410 floatMinutesY = std::max( floatMinutesY - 60, 0.0 );
411 degreesY++;
412 }
413
414 QString hemisphere;
415 QString sign;
416 if ( mUseSuffix )
417 {
418 hemisphere = wrappedY < 0 ? QObject::tr( "S" ) : QObject::tr( "N" );
419 }
420 else
421 {
422 if ( wrappedY < 0 )
423 {
424 sign = context.negativeSign();
425 }
426 }
427 //check if coordinate is all zeros for the specified precision, and if so,
428 //remove the sign and hemisphere strings
429 if ( degreesY == 0 && std::round( floatMinutesY * precisionMultiplier ) == 0 )
430 {
431 sign.clear();
432 hemisphere.clear();
433 }
434
435 ss << std::fixed << std::setprecision( numberDecimalPlaces() );
436 ss << floatMinutesY;
437 QString strMinutesY = QString::fromStdWString( ss.str() );
438 ss.str( std::wstring() );
439
440 trimTrailingZeros( strMinutesY, context );
441
442 //pad with leading digits if required
443 if ( mShowLeadingZeros && floatMinutesY < 10 )
444 strMinutesY = '0' + strMinutesY;
445
446 ss << std::fixed << std::setprecision( 0 );
447 ss << degreesY;
448 QString degreesYStr = QString::fromStdWString( ss.str() );
449 ss.str( std::wstring() );
450
451 if ( mShowLeadingDegreeZeros )
452 degreesYStr = QString( u"00"_s + degreesYStr ).right( 2 );
453
454 return sign + degreesYStr + QChar( 176 ) +
455 strMinutesY + QChar( 0x2032 ) +
456 hemisphere;
457}
458
459QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutes( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
460{
461 //first, limit longitude to -360 to 360 degree range
462 double wrappedX = std::fmod( val, 360.0 );
463 //next, wrap around longitudes > 180 or < -180 degrees, so that eg "190E" -> "170W"
464 if ( wrappedX > 180.0 )
465 {
466 wrappedX = wrappedX - 360.0;
467 }
468 else if ( wrappedX < -180.0 )
469 {
470 wrappedX = wrappedX + 360.0;
471 }
472
473 int degreesX = int( std::fabs( wrappedX ) );
474 double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
475
476 const double precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
477
478 //make sure rounding to specified precision doesn't create minutes >= 60
479 if ( std::round( floatMinutesX * precisionMultiplier ) >= 60 * precisionMultiplier )
480 {
481 floatMinutesX = std::max( floatMinutesX - 60, 0.0 );
482 degreesX++;
483 }
484
485 QString hemisphere;
486 QString sign;
487 if ( mUseSuffix )
488 {
489 hemisphere = wrappedX < 0 ? QObject::tr( "W" ) : QObject::tr( "E" );
490 }
491 else
492 {
493 if ( wrappedX < 0 )
494 {
495 sign = context.negativeSign();
496 }
497 }
498 //check if coordinate is all zeros for the specified precision, and if so,
499 //remove the sign and hemisphere strings
500 if ( degreesX == 0 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
501 {
502 sign.clear();
503 hemisphere.clear();
504 }
505
506 //also remove directional prefix from 180 degree longitudes
507 if ( degreesX == 180 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
508 {
509 hemisphere.clear();
510 }
511
512 ss << std::fixed << std::setprecision( numberDecimalPlaces() );
513 ss << floatMinutesX;
514 QString strMinutesX = QString::fromStdWString( ss.str() );
515 ss.str( std::wstring() );
516
517 trimTrailingZeros( strMinutesX, context );
518
519 //pad with leading digits if required
520 if ( mShowLeadingZeros && floatMinutesX < 10 )
521 strMinutesX = '0' + strMinutesX;
522
523 ss << std::fixed << std::setprecision( 0 );
524 ss << degreesX;
525 QString degreesXStr = QString::fromStdWString( ss.str() );
526 ss.str( std::wstring() );
527
528 if ( mShowLeadingDegreeZeros )
529 degreesXStr = QString( u"000"_s + degreesXStr ).right( 3 );
530
531 return sign + degreesXStr + QChar( 176 ) +
532 strMinutesX + QChar( 0x2032 ) +
533 hemisphere;
534}
535
536QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegrees( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
537{
538 //first, limit latitude to -180 to 180 degree range
539 double wrappedY = std::fmod( val, 180.0 );
540 //next, wrap around latitudes > 90 or < -90 degrees, so that eg "110S" -> "70N"
541 if ( wrappedY > 90.0 )
542 {
543 wrappedY = wrappedY - 180.0;
544 }
545 else if ( wrappedY < -90.0 )
546 {
547 wrappedY = wrappedY + 180.0;
548 }
549
550 const double absY = std::fabs( wrappedY );
551
552 const double precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
553
554 QString hemisphere;
555 QString sign;
556 if ( mUseSuffix )
557 {
558 hemisphere = wrappedY < 0 ? QObject::tr( "S" ) : QObject::tr( "N" );
559 }
560 else
561 {
562 if ( wrappedY < 0 )
563 {
564 sign = context.negativeSign();
565 }
566 }
567 //check if coordinate is all zeros for the specified precision, and if so,
568 //remove the sign and hemisphere strings
569 if ( std::round( absY * precisionMultiplier ) == 0 )
570 {
571 sign.clear();
572 hemisphere.clear();
573 }
574
575 ss << std::fixed << std::setprecision( numberDecimalPlaces() );
576 ss << absY;
577 QString strDegreesY = QString::fromStdWString( ss.str() );
578 ss.str( std::wstring() );
579
580 trimTrailingZeros( strDegreesY, context );
581
582 if ( mShowLeadingDegreeZeros && absY < 10 )
583 strDegreesY = '0' + strDegreesY;
584
585 return sign + strDegreesY + QChar( 176 ) + hemisphere;
586}
587
588QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegrees( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
589{
590 //first, limit longitude to -360 to 360 degree range
591 double wrappedX = std::fmod( val, 360.0 );
592 //next, wrap around longitudes > 180 or < -180 degrees, so that eg "190E" -> "170W"
593 if ( wrappedX > 180.0 )
594 {
595 wrappedX = wrappedX - 360.0;
596 }
597 else if ( wrappedX < -180.0 )
598 {
599 wrappedX = wrappedX + 360.0;
600 }
601
602 const double absX = std::fabs( wrappedX );
603
604 const double precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
605
606 QString hemisphere;
607 QString sign;
608 if ( mUseSuffix )
609 {
610 hemisphere = wrappedX < 0 ? QObject::tr( "W" ) : QObject::tr( "E" );
611 }
612 else
613 {
614 if ( wrappedX < 0 )
615 {
616 sign = context.negativeSign();
617 }
618 }
619 //check if coordinate is all zeros for the specified precision, and if so,
620 //remove the sign and hemisphere strings
621 if ( std::round( absX * precisionMultiplier ) == 0 )
622 {
623 sign.clear();
624 hemisphere.clear();
625 }
626
627 //also remove directional prefix from 180 degree longitudes
628 if ( std::round( absX * precisionMultiplier ) == 180 * precisionMultiplier )
629 {
630 sign.clear();
631 hemisphere.clear();
632 }
633
634 ss << std::fixed << std::setprecision( numberDecimalPlaces() );
635 ss << absX;
636 QString strDegreesX = QString::fromStdWString( ss.str() );
637 ss.str( std::wstring() );
638
639 trimTrailingZeros( strDegreesX, context );
640
641 if ( mShowLeadingDegreeZeros && absX < 100 )
642 strDegreesX = '0' + strDegreesX;
643 if ( mShowLeadingDegreeZeros && absX < 10 )
644 strDegreesX = '0' + strDegreesX;
645
646 return sign + strDegreesX + QChar( 176 ) + hemisphere;
647}
648
649void QgsGeographicCoordinateNumericFormat::trimTrailingZeros( QString &input, const QgsNumericFormatContext &context ) const
650{
651 const QChar decimal = decimalSeparator().isNull() ? context.decimalSeparator() : decimalSeparator();
652 if ( !showTrailingZeros() && input.contains( decimal ) )
653 {
654 int trimPoint = input.length() - 1;
655
656 while ( input.at( trimPoint ) == context.zeroDigit() )
657 trimPoint--;
658
659 if ( input.at( trimPoint ) == decimal )
660 trimPoint--;
661
662 input.truncate( trimPoint + 1 );
663 }
664}
QChar thousandsSeparator() const
Returns any override for the thousands separator character.
virtual void setConfiguration(const QVariantMap &configuration, const QgsReadWriteContext &context)
Sets the format's configuration.
bool showTrailingZeros() const
Returns true if trailing zeros will be shown (up to the specified numberDecimalPlaces()).
QChar decimalSeparator() const
Returns any override for the decimal separator character.
int numberDecimalPlaces() const
Returns the maximum number of decimal places to show.
QVariantMap configuration(const QgsReadWriteContext &context) const override
Returns the current configuration of the formatter.
void setConfiguration(const QVariantMap &configuration, const QgsReadWriteContext &context) override
Sets the format's configuration.
@ DegreesMinutes
Degrees and decimal minutes, eg 30 degrees 45.55'.
@ DegreesMinutesSeconds
Degrees, minutes and seconds, eg 30 degrees 45'30.
QgsNumericFormat * create(const QVariantMap &configuration, const QgsReadWriteContext &context) const override
Creates a new copy of the format, using the supplied configuration.
void setShowDirectionalSuffix(bool show)
Sets whether directional suffixes (e.g.
QgsGeographicCoordinateNumericFormat * clone() const override
Clones the format, returning a new object.
double suggestSampleValue() const override
Returns a suggested sample value which nicely represents the current format configuration.
int sortKey() override
Returns a sorting key value, where formats with a lower sort key will be shown earlier in lists.
QString id() const override
Returns a unique id for this numeric format.
void setShowDegreeLeadingZeros(bool show)
Sets whether leading zeros for the degree values should be shown.
QString formatDouble(double value, const QgsNumericFormatContext &context) const override
Returns a formatted string representation of a numeric double value.
bool showDirectionalSuffix() const
Returns true if directional suffixes (e.g.
QVariantMap configuration(const QgsReadWriteContext &context) const override
Returns the current configuration of the formatter.
void setShowLeadingZeros(bool show)
Sets whether leading zeros in the minutes or seconds values should be shown.
AngleFormat angleFormat() const
Returns the angle format, which controls how bearing the angles are formatted described in the return...
bool showLeadingZeros() const
Returns true if leading zeros in the minutes or seconds values should be shown.
bool showDegreeLeadingZeros() const
Returns true if leading zeros for the degree values should be shown.
QString visibleName() const override
Returns the translated, user-visible name for this format.
void setAngleFormat(AngleFormat format)
Sets the directional formatting option, which controls how bearing the angles are formatted described...
A context for numeric formats.
QChar negativeSign() const
Returns the negative sign character.
QChar thousandsSeparator() const
Returns the thousands separator character.
QChar zeroDigit() const
Returns the zero digit character.
Interpretation interpretation() const
Returns the interpretation of the numbers being converted.
QChar decimalSeparator() const
Returns the decimal separator character.
static constexpr int DEFAULT_SORT_KEY
QgsNumericFormat()=default
A container for the context for various read/write operations on objects.
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
Definition qgis.h:7110
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition qgis.h:7091
#define BUILTIN_UNREACHABLE
Definition qgis.h:7489