QGIS API Documentation  3.27.0-Master (bef583a8ef)
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 #include "qgis.h"
18 #include "qgscoordinateformatter.h"
19 
20 #include <memory>
21 #include <iostream>
22 #include <locale>
23 #include <iomanip>
24 
25 struct formatter : std::numpunct<wchar_t>
26 {
27  formatter( QChar thousands, bool showThousands, QChar decimal )
28  : mThousands( thousands.unicode() )
29  , mDecimal( decimal.unicode() )
30  , mShowThousands( showThousands )
31  {}
32  wchar_t do_decimal_point() const override { return mDecimal; }
33  wchar_t do_thousands_sep() const override { return mThousands; }
34  std::string do_grouping() const override { return mShowThousands ? "\3" : "\0"; }
35 
36  wchar_t mThousands;
37  wchar_t mDecimal;
38  bool mShowThousands = true;
39 };
40 
41 
43 {
44 }
45 
47 {
48  return QStringLiteral( "geographiccoordinate" );
49 }
50 
52 {
53  return QObject::tr( "Geographic Coordinate" );
54 }
55 
57 {
58  return DEFAULT_SORT_KEY;
59 }
60 
62 {
63  return 3.7555;
64 }
65 
67 {
68  const QChar decimal = decimalSeparator().isNull() ? context.decimalSeparator() : decimalSeparator();
69  std::basic_stringstream<wchar_t> os;
70  os.imbue( std::locale( os.getloc(), new formatter( thousandsSeparator().isNull() ? context.thousandsSeparator() : thousandsSeparator(),
71  false,
72  decimal ) ) );
73 
74  switch ( context.interpretation() )
75  {
77  return formatLatitude( value, os, context );
78 
81  return formatLongitude( value, os, context );
82  }
84 }
85 
87 {
88  return new QgsGeographicCoordinateNumericFormat( *this );
89 }
90 
91 QgsNumericFormat *QgsGeographicCoordinateNumericFormat::create( const QVariantMap &configuration, const QgsReadWriteContext &context ) const
92 {
93  std::unique_ptr< QgsGeographicCoordinateNumericFormat > res = std::make_unique< QgsGeographicCoordinateNumericFormat >();
94  res->setConfiguration( configuration, context );
95  res->mAngleFormat = qgsEnumKeyToValue( configuration.value( QStringLiteral( "angle_format" ) ).toString(), AngleFormat::DecimalDegrees );
96  res->mShowLeadingZeros = configuration.value( QStringLiteral( "show_leading_zeros" ), false ).toBool();
97  res->mShowLeadingDegreeZeros = configuration.value( QStringLiteral( "show_leading_degree_zeros" ), false ).toBool();
98  res->mUseSuffix = configuration.value( QStringLiteral( "show_suffix" ), false ).toBool();
99  return res.release();
100 }
101 
103 {
104  QVariantMap res = QgsBasicNumericFormat::configuration( context );
105  res.insert( QStringLiteral( "angle_format" ), qgsEnumValueToKey( mAngleFormat ) );
106  res.insert( QStringLiteral( "show_leading_zeros" ), mShowLeadingZeros );
107  res.insert( QStringLiteral( "show_leading_degree_zeros" ), mShowLeadingDegreeZeros );
108  res.insert( QStringLiteral( "show_suffix" ), mUseSuffix );
109  return res;
110 }
111 
113 {
114  return mAngleFormat;
115 }
116 
118 {
119  mAngleFormat = format;
120 }
121 
122 void QgsGeographicCoordinateNumericFormat::setConfiguration( const QVariantMap &configuration, const QgsReadWriteContext &context )
123 {
125  mAngleFormat = qgsEnumKeyToValue( configuration.value( QStringLiteral( "angle_format" ) ).toString(), AngleFormat::DecimalDegrees );
126  mShowLeadingZeros = configuration.value( QStringLiteral( "show_leading_zeros" ), false ).toBool();
127  mShowLeadingDegreeZeros = configuration.value( QStringLiteral( "show_leading_degree_zeros" ), false ).toBool();
128  mUseSuffix = configuration.value( QStringLiteral( "show_suffix" ), false ).toBool();
129 }
130 
132 {
133  return mShowLeadingZeros;
134 }
135 
137 {
138  mShowLeadingZeros = newShowLeadingZeros;
139 }
140 
142 {
143  return mShowLeadingDegreeZeros;
144 }
145 
147 {
148  mShowLeadingDegreeZeros = show;
149 }
150 
152 {
153  return mUseSuffix;
154 }
155 
157 {
158  mUseSuffix = show;
159 }
160 
161 QString QgsGeographicCoordinateNumericFormat::formatLongitude( double value, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
162 {
163  switch ( mAngleFormat )
164  {
166  return formatLongitudeAsDegreesMinutesSeconds( value, ss, context );
168  return formatLongitudeAsDegreesMinutes( value, ss, context );
170  return formatLongitudeAsDegrees( value, ss, context );
171  }
173 }
174 
175 QString QgsGeographicCoordinateNumericFormat::formatLatitude( double value, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
176 {
177  switch ( mAngleFormat )
178  {
180  return formatLatitudeAsDegreesMinutesSeconds( value, ss, context );
182  return formatLatitudeAsDegreesMinutes( value, ss, context );
184  return formatLatitudeAsDegrees( value, ss, context );
185  }
187 }
188 
189 QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutesSeconds( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
190 {
191  //first, limit latitude to -180 to 180 degree range
192  double wrappedY = std::fmod( val, 180.0 );
193  //next, wrap around latitudes > 90 or < -90 degrees, so that eg "110S" -> "70N"
194  if ( wrappedY > 90.0 )
195  {
196  wrappedY = wrappedY - 180.0;
197  }
198  else if ( wrappedY < -90.0 )
199  {
200  wrappedY = wrappedY + 180.0;
201  }
202 
203  const int precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
204 
205  int degreesY = int( std::fabs( wrappedY ) );
206  const double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
207  int intMinutesY = int( floatMinutesY );
208  double secondsY = ( floatMinutesY - intMinutesY ) * 60.0;
209 
210  //make sure rounding to specified precision doesn't create seconds >= 60
211  if ( std::round( secondsY * precisionMultiplier ) >= 60 * precisionMultiplier )
212  {
213  secondsY = std::max( secondsY - 60, 0.0 );
214  intMinutesY++;
215  if ( intMinutesY >= 60 )
216  {
217  intMinutesY -= 60;
218  degreesY++;
219  }
220  }
221 
222  QString hemisphere;
223  QString sign;
224  if ( mUseSuffix )
225  {
226  hemisphere = wrappedY < 0 ? QObject::tr( "S" ) : QObject::tr( "N" );
227  }
228  else
229  {
230  if ( wrappedY < 0 )
231  {
232  sign = context.negativeSign();
233  }
234  }
235  //check if coordinate is all zeros for the specified precision, and if so,
236  //remove the sign and hemisphere strings
237  if ( degreesY == 0 && intMinutesY == 0 && std::round( secondsY * precisionMultiplier ) == 0 )
238  {
239  sign = QString();
240  hemisphere.clear();
241  }
242 
243  QString strMinutesY;
244  QString strSecondsY;
245 
246  ss << std::fixed << std::setprecision( 0 );
247  ss << intMinutesY;
248 
249  strMinutesY = QString::fromStdWString( ss.str() );
250  ss.str( std::wstring() );
251 
252  ss << std::fixed << std::setprecision( numberDecimalPlaces() );
253  ss << secondsY;
254  strSecondsY = QString::fromStdWString( ss.str() );
255  ss.str( std::wstring() );
256 
257  trimTrailingZeros( strSecondsY, context );
258 
259  //pad with leading digits if required
260  if ( mShowLeadingZeros && intMinutesY < 10 )
261  strMinutesY = '0' + strMinutesY;
262 
263  if ( mShowLeadingZeros && secondsY < 10 )
264  strSecondsY = '0' + strSecondsY;
265 
266  ss << std::fixed << std::setprecision( 0 );
267  ss << degreesY;
268  QString degreesYStr = QString::fromStdWString( ss.str() );
269  ss.str( std::wstring() );
270 
271  if ( mShowLeadingDegreeZeros )
272  degreesYStr = QString( QStringLiteral( "00" ) + degreesYStr ).right( 2 );
273 
274  return sign + degreesYStr + QChar( 176 ) +
275  strMinutesY + QChar( 0x2032 ) +
276  strSecondsY + QChar( 0x2033 ) +
277  hemisphere;
278 }
279 
280 QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutesSeconds( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
281 {
282  //first, limit longitude to -360 to 360 degree range
283  double wrappedX = std::fmod( val, 360.0 );
284  //next, wrap around longitudes > 180 or < -180 degrees, so that eg "190E" -> "170W"
285  if ( wrappedX > 180.0 )
286  {
287  wrappedX = wrappedX - 360.0;
288  }
289  else if ( wrappedX < -180.0 )
290  {
291  wrappedX = wrappedX + 360.0;
292  }
293 
294  const int precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
295 
296  int degreesX = int( std::fabs( wrappedX ) );
297  const double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
298  int intMinutesX = int( floatMinutesX );
299  double secondsX = ( floatMinutesX - intMinutesX ) * 60.0;
300 
301  //make sure rounding to specified precision doesn't create seconds >= 60
302  if ( std::round( secondsX * precisionMultiplier ) >= 60 * precisionMultiplier )
303  {
304  secondsX = std::max( secondsX - 60, 0.0 );
305  intMinutesX++;
306  if ( intMinutesX >= 60 )
307  {
308  intMinutesX -= 60;
309  degreesX++;
310  }
311  }
312 
313  QString hemisphere;
314  QString sign;
315  if ( mUseSuffix )
316  {
317  hemisphere = wrappedX < 0 ? QObject::tr( "W" ) : QObject::tr( "E" );
318  }
319  else
320  {
321  if ( wrappedX < 0 )
322  {
323  sign = context.negativeSign();
324  }
325  }
326  //check if coordinate is all zeros for the specified precision, and if so,
327  //remove the sign and hemisphere strings
328  if ( degreesX == 0 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
329  {
330  sign.clear();
331  hemisphere.clear();
332  }
333 
334  //also remove directional prefix from 180 degree longitudes
335  if ( degreesX == 180 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
336  {
337  hemisphere.clear();
338  }
339 
340  QString minutesX;
341  QString strSecondsX;
342 
343  ss << std::fixed << std::setprecision( 0 );
344  ss << intMinutesX;
345 
346  minutesX = QString::fromStdWString( ss.str() );
347  ss.str( std::wstring() );
348 
349  ss << std::fixed << std::setprecision( numberDecimalPlaces() );
350  ss << secondsX;
351  strSecondsX = QString::fromStdWString( ss.str() );
352  ss.str( std::wstring() );
353 
354  trimTrailingZeros( strSecondsX, context );
355 
356  //pad with leading digits if required
357  if ( mShowLeadingZeros && intMinutesX < 10 )
358  minutesX = '0' + minutesX;
359 
360  if ( mShowLeadingZeros && secondsX < 10 )
361  strSecondsX = '0' + strSecondsX;
362 
363  ss << std::fixed << std::setprecision( 0 );
364  ss << degreesX;
365  QString degreesXStr = QString::fromStdWString( ss.str() );
366  ss.str( std::wstring() );
367 
368  if ( mShowLeadingDegreeZeros )
369  degreesXStr = QString( QStringLiteral( "000" ) + degreesXStr ).right( 3 );
370 
371  return sign + degreesXStr + QChar( 176 ) +
372  minutesX + QChar( 0x2032 ) +
373  strSecondsX + QChar( 0x2033 ) +
374  hemisphere;
375 }
376 
377 QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutes( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
378 {
379  //first, limit latitude to -180 to 180 degree range
380  double wrappedY = std::fmod( val, 180.0 );
381  //next, wrap around latitudes > 90 or < -90 degrees, so that eg "110S" -> "70N"
382  if ( wrappedY > 90.0 )
383  {
384  wrappedY = wrappedY - 180.0;
385  }
386  else if ( wrappedY < -90.0 )
387  {
388  wrappedY = wrappedY + 180.0;
389  }
390 
391  int degreesY = int( std::fabs( wrappedY ) );
392  double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
393 
394  const int precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
395 
396  //make sure rounding to specified precision doesn't create minutes >= 60
397  if ( std::round( floatMinutesY * precisionMultiplier ) >= 60 * precisionMultiplier )
398  {
399  floatMinutesY = std::max( floatMinutesY - 60, 0.0 );
400  degreesY++;
401  }
402 
403  QString hemisphere;
404  QString sign;
405  if ( mUseSuffix )
406  {
407  hemisphere = wrappedY < 0 ? QObject::tr( "S" ) : QObject::tr( "N" );
408  }
409  else
410  {
411  if ( wrappedY < 0 )
412  {
413  sign = context.negativeSign();
414  }
415  }
416  //check if coordinate is all zeros for the specified precision, and if so,
417  //remove the sign and hemisphere strings
418  if ( degreesY == 0 && std::round( floatMinutesY * precisionMultiplier ) == 0 )
419  {
420  sign.clear();
421  hemisphere.clear();
422  }
423 
424  ss << std::fixed << std::setprecision( numberDecimalPlaces() );
425  ss << floatMinutesY;
426  QString strMinutesY = QString::fromStdWString( ss.str() );
427  ss.str( std::wstring() );
428 
429  trimTrailingZeros( strMinutesY, context );
430 
431  //pad with leading digits if required
432  if ( mShowLeadingZeros && floatMinutesY < 10 )
433  strMinutesY = '0' + strMinutesY;
434 
435  ss << std::fixed << std::setprecision( 0 );
436  ss << degreesY;
437  QString degreesYStr = QString::fromStdWString( ss.str() );
438  ss.str( std::wstring() );
439 
440  if ( mShowLeadingDegreeZeros )
441  degreesYStr = QString( QStringLiteral( "00" ) + degreesYStr ).right( 2 );
442 
443  return sign + degreesYStr + QChar( 176 ) +
444  strMinutesY + QChar( 0x2032 ) +
445  hemisphere;
446 }
447 
448 QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutes( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
449 {
450  //first, limit longitude to -360 to 360 degree range
451  double wrappedX = std::fmod( val, 360.0 );
452  //next, wrap around longitudes > 180 or < -180 degrees, so that eg "190E" -> "170W"
453  if ( wrappedX > 180.0 )
454  {
455  wrappedX = wrappedX - 360.0;
456  }
457  else if ( wrappedX < -180.0 )
458  {
459  wrappedX = wrappedX + 360.0;
460  }
461 
462  int degreesX = int( std::fabs( wrappedX ) );
463  double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
464 
465  const int precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
466 
467  //make sure rounding to specified precision doesn't create minutes >= 60
468  if ( std::round( floatMinutesX * precisionMultiplier ) >= 60 * precisionMultiplier )
469  {
470  floatMinutesX = std::max( floatMinutesX - 60, 0.0 );
471  degreesX++;
472  }
473 
474  QString hemisphere;
475  QString sign;
476  if ( mUseSuffix )
477  {
478  hemisphere = wrappedX < 0 ? QObject::tr( "W" ) : QObject::tr( "E" );
479  }
480  else
481  {
482  if ( wrappedX < 0 )
483  {
484  sign = context.negativeSign();
485  }
486  }
487  //check if coordinate is all zeros for the specified precision, and if so,
488  //remove the sign and hemisphere strings
489  if ( degreesX == 0 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
490  {
491  sign.clear();
492  hemisphere.clear();
493  }
494 
495  //also remove directional prefix from 180 degree longitudes
496  if ( degreesX == 180 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
497  {
498  hemisphere.clear();
499  }
500 
501  ss << std::fixed << std::setprecision( numberDecimalPlaces() );
502  ss << floatMinutesX;
503  QString strMinutesX = QString::fromStdWString( ss.str() );
504  ss.str( std::wstring() );
505 
506  trimTrailingZeros( strMinutesX, context );
507 
508  //pad with leading digits if required
509  if ( mShowLeadingZeros && floatMinutesX < 10 )
510  strMinutesX = '0' + strMinutesX;
511 
512  ss << std::fixed << std::setprecision( 0 );
513  ss << degreesX;
514  QString degreesXStr = QString::fromStdWString( ss.str() );
515  ss.str( std::wstring() );
516 
517  if ( mShowLeadingDegreeZeros )
518  degreesXStr = QString( QStringLiteral( "000" ) + degreesXStr ).right( 3 );
519 
520  return sign + degreesXStr + QChar( 176 ) +
521  strMinutesX + QChar( 0x2032 ) +
522  hemisphere;
523 }
524 
525 QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegrees( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
526 {
527  //first, limit latitude to -180 to 180 degree range
528  double wrappedY = std::fmod( val, 180.0 );
529  //next, wrap around latitudes > 90 or < -90 degrees, so that eg "110S" -> "70N"
530  if ( wrappedY > 90.0 )
531  {
532  wrappedY = wrappedY - 180.0;
533  }
534  else if ( wrappedY < -90.0 )
535  {
536  wrappedY = wrappedY + 180.0;
537  }
538 
539  const double absY = std::fabs( wrappedY );
540 
541  const int precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
542 
543  QString hemisphere;
544  QString sign;
545  if ( mUseSuffix )
546  {
547  hemisphere = wrappedY < 0 ? QObject::tr( "S" ) : QObject::tr( "N" );
548  }
549  else
550  {
551  if ( wrappedY < 0 )
552  {
553  sign = context.negativeSign();
554  }
555  }
556  //check if coordinate is all zeros for the specified precision, and if so,
557  //remove the sign and hemisphere strings
558  if ( std::round( absY * precisionMultiplier ) == 0 )
559  {
560  sign.clear();
561  hemisphere.clear();
562  }
563 
564  ss << std::fixed << std::setprecision( numberDecimalPlaces() );
565  ss << absY;
566  QString strDegreesY = QString::fromStdWString( ss.str() );
567  ss.str( std::wstring() );
568 
569  trimTrailingZeros( strDegreesY, context );
570 
571  if ( mShowLeadingDegreeZeros && absY < 10 )
572  strDegreesY = '0' + strDegreesY;
573 
574  return sign + strDegreesY + QChar( 176 ) + hemisphere;
575 }
576 
577 QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegrees( double val, std::basic_stringstream<wchar_t> &ss, const QgsNumericFormatContext &context ) const
578 {
579  //first, limit longitude to -360 to 360 degree range
580  double wrappedX = std::fmod( val, 360.0 );
581  //next, wrap around longitudes > 180 or < -180 degrees, so that eg "190E" -> "170W"
582  if ( wrappedX > 180.0 )
583  {
584  wrappedX = wrappedX - 360.0;
585  }
586  else if ( wrappedX < -180.0 )
587  {
588  wrappedX = wrappedX + 360.0;
589  }
590 
591  const double absX = std::fabs( wrappedX );
592 
593  const int precisionMultiplier = std::pow( 10.0, numberDecimalPlaces() );
594 
595  QString hemisphere;
596  QString sign;
597  if ( mUseSuffix )
598  {
599  hemisphere = wrappedX < 0 ? QObject::tr( "W" ) : QObject::tr( "E" );
600  }
601  else
602  {
603  if ( wrappedX < 0 )
604  {
605  sign = context.negativeSign();
606  }
607  }
608  //check if coordinate is all zeros for the specified precision, and if so,
609  //remove the sign and hemisphere strings
610  if ( std::round( absX * precisionMultiplier ) == 0 )
611  {
612  sign.clear();
613  hemisphere.clear();
614  }
615 
616  //also remove directional prefix from 180 degree longitudes
617  if ( std::round( absX * precisionMultiplier ) == 180 * precisionMultiplier )
618  {
619  sign.clear();
620  hemisphere.clear();
621  }
622 
623  ss << std::fixed << std::setprecision( numberDecimalPlaces() );
624  ss << absX;
625  QString strDegreesX = QString::fromStdWString( ss.str() );
626  ss.str( std::wstring() );
627 
628  trimTrailingZeros( strDegreesX, context );
629 
630  if ( mShowLeadingDegreeZeros && absX < 100 )
631  strDegreesX = '0' + strDegreesX;
632  if ( mShowLeadingDegreeZeros && absX < 10 )
633  strDegreesX = '0' + strDegreesX;
634 
635  return sign + strDegreesX + QChar( 176 ) + hemisphere;
636 }
637 
638 void QgsGeographicCoordinateNumericFormat::trimTrailingZeros( QString &input, const QgsNumericFormatContext &context ) const
639 {
640  const QChar decimal = decimalSeparator().isNull() ? context.decimalSeparator() : decimalSeparator();
641  if ( !showTrailingZeros() && input.contains( decimal ) )
642  {
643  int trimPoint = input.length() - 1;
644 
645  while ( input.at( trimPoint ) == context.zeroDigit() )
646  trimPoint--;
647 
648  if ( input.at( trimPoint ) == decimal )
649  trimPoint--;
650 
651  input.truncate( trimPoint + 1 );
652  }
653 }
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.
A numeric formatter which returns a text representation of a geographic coordinate (latitude or longi...
void setConfiguration(const QVariantMap &configuration, const QgsReadWriteContext &context) override
Sets the format's configuration.
@ DegreesMinutes
Degrees and decimal minutes, eg 30 degrees 45.55'.
@ DecimalDegrees
Decimal degrees, eg 30.7555 degrees.
@ 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.
A numeric formatter allows for formatting a numeric value for display, using a variety of different f...
static constexpr int DEFAULT_SORT_KEY
The class is used as a container of context for various read/write operations on other 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:2454
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
Definition: qgis.h:2435
#define BUILTIN_UNREACHABLE
Definition: qgis.h:2902
wchar_t do_decimal_point() const override
std::string do_grouping() const override
wchar_t do_thousands_sep() const override
formatter(QChar thousands, bool showThousands, QChar decimal)