27   formatter( QChar thousands, 
bool showThousands, QChar decimal )
 
   48   return QStringLiteral( 
"geographiccoordinate" );
 
   53   return QObject::tr( 
"Geographic Coordinate" );
 
   69   std::basic_stringstream<wchar_t> os;
 
   77       return formatLatitude( value, os, context );
 
   81       return formatLongitude( value, os, context );
 
   93   std::unique_ptr< QgsGeographicCoordinateNumericFormat > res = std::make_unique< QgsGeographicCoordinateNumericFormat >();
 
   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();
 
  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 );
 
  119   mAngleFormat = format;
 
  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();
 
  133   return mShowLeadingZeros;
 
  138   mShowLeadingZeros = newShowLeadingZeros;
 
  143   return mShowLeadingDegreeZeros;
 
  148   mShowLeadingDegreeZeros = show;
 
  161 QString QgsGeographicCoordinateNumericFormat::formatLongitude( 
double value, std::basic_stringstream<wchar_t> &ss, 
const QgsNumericFormatContext &context )
 const 
  163   switch ( mAngleFormat )
 
  166       return formatLongitudeAsDegreesMinutesSeconds( value, ss, context );
 
  168       return formatLongitudeAsDegreesMinutes( value, ss,  context );
 
  170       return formatLongitudeAsDegrees( value, ss, context );
 
  175 QString QgsGeographicCoordinateNumericFormat::formatLatitude( 
double value, std::basic_stringstream<wchar_t> &ss, 
const QgsNumericFormatContext &context )
 const 
  177   switch ( mAngleFormat )
 
  180       return formatLatitudeAsDegreesMinutesSeconds( value, ss, context );
 
  182       return formatLatitudeAsDegreesMinutes( value, ss, context );
 
  184       return formatLatitudeAsDegrees( value, ss, context );
 
  189 QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutesSeconds( 
double val, std::basic_stringstream<wchar_t> &ss, 
const QgsNumericFormatContext &context )
 const 
  192   double wrappedY = std::fmod( val, 180.0 );
 
  194   if ( wrappedY > 90.0 )
 
  196     wrappedY = wrappedY - 180.0;
 
  198   else if ( wrappedY < -90.0 )
 
  200     wrappedY = wrappedY + 180.0;
 
  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;
 
  211   if ( std::round( secondsY * precisionMultiplier ) >= 60 * precisionMultiplier )
 
  213     secondsY = std::max( secondsY - 60, 0.0 );
 
  215     if ( intMinutesY >= 60 )
 
  226     hemisphere = wrappedY < 0 ? QObject::tr( 
"S" ) : QObject::tr( 
"N" );
 
  237   if ( degreesY == 0 && intMinutesY == 0 && std::round( secondsY * precisionMultiplier ) == 0 )
 
  246   ss << std::fixed << std::setprecision( 0 );
 
  249   strMinutesY = QString::fromStdWString( ss.str() );
 
  250   ss.str( std::wstring() );
 
  254   strSecondsY = QString::fromStdWString( ss.str() );
 
  255   ss.str( std::wstring() );
 
  257   trimTrailingZeros( strSecondsY, context );
 
  260   if ( mShowLeadingZeros && intMinutesY < 10 )
 
  261     strMinutesY = 
'0' + strMinutesY;
 
  263   if ( mShowLeadingZeros && secondsY < 10 )
 
  264     strSecondsY = 
'0' + strSecondsY;
 
  266   ss << std::fixed << std::setprecision( 0 );
 
  268   QString degreesYStr = QString::fromStdWString( ss.str() );
 
  269   ss.str( std::wstring() );
 
  271   if ( mShowLeadingDegreeZeros )
 
  272     degreesYStr = QString( QStringLiteral( 
"00" ) + degreesYStr ).right( 2 );
 
  274   return sign + degreesYStr + QChar( 176 ) +
 
  275          strMinutesY + QChar( 0x2032 ) +
 
  276          strSecondsY + QChar( 0x2033 ) +
 
  280 QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutesSeconds( 
double val, std::basic_stringstream<wchar_t> &ss, 
const QgsNumericFormatContext &context )
 const 
  283   double wrappedX = std::fmod( val, 360.0 );
 
  285   if ( wrappedX > 180.0 )
 
  287     wrappedX = wrappedX - 360.0;
 
  289   else if ( wrappedX < -180.0 )
 
  291     wrappedX = wrappedX + 360.0;
 
  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;
 
  302   if ( std::round( secondsX * precisionMultiplier ) >= 60 * precisionMultiplier )
 
  304     secondsX = std::max( secondsX - 60, 0.0 );
 
  306     if ( intMinutesX >= 60 )
 
  317     hemisphere = wrappedX < 0 ? QObject::tr( 
"W" ) : QObject::tr( 
"E" );
 
  328   if ( degreesX == 0 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
 
  335   if ( degreesX == 180 && intMinutesX == 0 && std::round( secondsX * precisionMultiplier ) == 0 )
 
  343   ss << std::fixed << std::setprecision( 0 );
 
  346   minutesX = QString::fromStdWString( ss.str() );
 
  347   ss.str( std::wstring() );
 
  351   strSecondsX = QString::fromStdWString( ss.str() );
 
  352   ss.str( std::wstring() );
 
  354   trimTrailingZeros( strSecondsX, context );
 
  357   if ( mShowLeadingZeros && intMinutesX < 10 )
 
  358     minutesX = 
'0' + minutesX;
 
  360   if ( mShowLeadingZeros && secondsX < 10 )
 
  361     strSecondsX = 
'0' + strSecondsX;
 
  363   ss << std::fixed << std::setprecision( 0 );
 
  365   QString degreesXStr = QString::fromStdWString( ss.str() );
 
  366   ss.str( std::wstring() );
 
  368   if ( mShowLeadingDegreeZeros )
 
  369     degreesXStr = QString( QStringLiteral( 
"000" ) + degreesXStr ).right( 3 );
 
  371   return sign + degreesXStr + QChar( 176 ) +
 
  372          minutesX + QChar( 0x2032 ) +
 
  373          strSecondsX + QChar( 0x2033 ) +
 
  377 QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegreesMinutes( 
double val, std::basic_stringstream<wchar_t> &ss, 
const QgsNumericFormatContext &context )
 const 
  380   double wrappedY = std::fmod( val, 180.0 );
 
  382   if ( wrappedY > 90.0 )
 
  384     wrappedY = wrappedY - 180.0;
 
  386   else if ( wrappedY < -90.0 )
 
  388     wrappedY = wrappedY + 180.0;
 
  391   int degreesY = int( std::fabs( wrappedY ) );
 
  392   double floatMinutesY = ( std::fabs( wrappedY ) - degreesY ) * 60.0;
 
  397   if ( std::round( floatMinutesY * precisionMultiplier ) >= 60 * precisionMultiplier )
 
  399     floatMinutesY = std::max( floatMinutesY - 60, 0.0 );
 
  407     hemisphere = wrappedY < 0 ? QObject::tr( 
"S" ) : QObject::tr( 
"N" );
 
  418   if ( degreesY == 0 && std::round( floatMinutesY * precisionMultiplier ) == 0 )
 
  426   QString strMinutesY = QString::fromStdWString( ss.str() );
 
  427   ss.str( std::wstring() );
 
  429   trimTrailingZeros( strMinutesY, context );
 
  432   if ( mShowLeadingZeros && floatMinutesY < 10 )
 
  433     strMinutesY = 
'0' + strMinutesY;
 
  435   ss << std::fixed << std::setprecision( 0 );
 
  437   QString degreesYStr = QString::fromStdWString( ss.str() );
 
  438   ss.str( std::wstring() );
 
  440   if ( mShowLeadingDegreeZeros )
 
  441     degreesYStr = QString( QStringLiteral( 
"00" ) + degreesYStr ).right( 2 );
 
  443   return sign + degreesYStr + QChar( 176 ) +
 
  444          strMinutesY + QChar( 0x2032 ) +
 
  448 QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegreesMinutes( 
double val, std::basic_stringstream<wchar_t> &ss, 
const QgsNumericFormatContext &context )
 const 
  451   double wrappedX = std::fmod( val, 360.0 );
 
  453   if ( wrappedX > 180.0 )
 
  455     wrappedX = wrappedX - 360.0;
 
  457   else if ( wrappedX < -180.0 )
 
  459     wrappedX = wrappedX + 360.0;
 
  462   int degreesX = int( std::fabs( wrappedX ) );
 
  463   double floatMinutesX = ( std::fabs( wrappedX ) - degreesX ) * 60.0;
 
  468   if ( std::round( floatMinutesX * precisionMultiplier ) >= 60 * precisionMultiplier )
 
  470     floatMinutesX = std::max( floatMinutesX - 60, 0.0 );
 
  478     hemisphere = wrappedX < 0 ? QObject::tr( 
"W" ) : QObject::tr( 
"E" );
 
  489   if ( degreesX == 0 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
 
  496   if ( degreesX == 180 && std::round( floatMinutesX * precisionMultiplier ) == 0 )
 
  503   QString strMinutesX = QString::fromStdWString( ss.str() );
 
  504   ss.str( std::wstring() );
 
  506   trimTrailingZeros( strMinutesX, context );
 
  509   if ( mShowLeadingZeros && floatMinutesX < 10 )
 
  510     strMinutesX = 
'0' + strMinutesX;
 
  512   ss << std::fixed << std::setprecision( 0 );
 
  514   QString degreesXStr = QString::fromStdWString( ss.str() );
 
  515   ss.str( std::wstring() );
 
  517   if ( mShowLeadingDegreeZeros )
 
  518     degreesXStr = QString( QStringLiteral( 
"000" ) + degreesXStr ).right( 3 );
 
  520   return sign + degreesXStr + QChar( 176 ) +
 
  521          strMinutesX + QChar( 0x2032 ) +
 
  525 QString QgsGeographicCoordinateNumericFormat::formatLatitudeAsDegrees( 
double val, std::basic_stringstream<wchar_t> &ss, 
const QgsNumericFormatContext &context )
 const 
  528   double wrappedY = std::fmod( val, 180.0 );
 
  530   if ( wrappedY > 90.0 )
 
  532     wrappedY = wrappedY - 180.0;
 
  534   else if ( wrappedY < -90.0 )
 
  536     wrappedY = wrappedY + 180.0;
 
  539   const double absY = std::fabs( wrappedY );
 
  547     hemisphere = wrappedY < 0 ? QObject::tr( 
"S" ) : QObject::tr( 
"N" );
 
  558   if ( std::round( absY * precisionMultiplier ) == 0 )
 
  566   QString strDegreesY = QString::fromStdWString( ss.str() );
 
  567   ss.str( std::wstring() );
 
  569   trimTrailingZeros( strDegreesY, context );
 
  571   if ( mShowLeadingDegreeZeros && absY < 10 )
 
  572     strDegreesY = 
'0' + strDegreesY;
 
  574   return sign + strDegreesY + QChar( 176 ) + hemisphere;
 
  577 QString QgsGeographicCoordinateNumericFormat::formatLongitudeAsDegrees( 
double val, std::basic_stringstream<wchar_t> &ss, 
const QgsNumericFormatContext &context )
 const 
  580   double wrappedX = std::fmod( val, 360.0 );
 
  582   if ( wrappedX > 180.0 )
 
  584     wrappedX = wrappedX - 360.0;
 
  586   else if ( wrappedX < -180.0 )
 
  588     wrappedX = wrappedX + 360.0;
 
  591   const double absX = std::fabs( wrappedX );
 
  599     hemisphere = wrappedX < 0 ? QObject::tr( 
"W" ) : QObject::tr( 
"E" );
 
  610   if ( std::round( absX * precisionMultiplier ) == 0 )
 
  617   if ( std::round( absX * precisionMultiplier ) == 180 * precisionMultiplier )
 
  625   QString strDegreesX = QString::fromStdWString( ss.str() );
 
  626   ss.str( std::wstring() );
 
  628   trimTrailingZeros( strDegreesX, context );
 
  630   if ( mShowLeadingDegreeZeros && absX < 100 )
 
  631     strDegreesX = 
'0' + strDegreesX;
 
  632   if ( mShowLeadingDegreeZeros && absX < 10 )
 
  633     strDegreesX = 
'0' + strDegreesX;
 
  635   return sign + strDegreesX + QChar( 176 ) + hemisphere;
 
  638 void QgsGeographicCoordinateNumericFormat::trimTrailingZeros( QString &input, 
const QgsNumericFormatContext &context )
 const 
  643     int trimPoint = input.length() - 1;
 
  645     while ( input.at( trimPoint ) == context.
zeroDigit() )
 
  648     if ( input.at( trimPoint ) == decimal )
 
  651     input.truncate( trimPoint + 1 );