Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[processing] Fix invalid characters in HTML for 'Raster layer unique …
…values' report
  • Loading branch information
nyalldawson committed May 31, 2018
1 parent 8bdec09 commit f7a6864
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 6 deletions.
8 changes: 8 additions & 0 deletions python/core/auto_generated/qgsstringutils.sip.in
Expand Up @@ -187,6 +187,14 @@ Converts a string by applying capitalization rules to the string.
:return: capitalized string

.. versionadded:: 3.0
%End

static QString ampersandEncode( const QString &string );
%Docstring
Replaces any extended unicode characters with the XML style é encoded versions
of these characeters.

.. versionadded:: 3.2
%End

static int levenshteinDistance( const QString &string1, const QString &string2, bool caseSensitive = false );
Expand Down
Binary file not shown.
13 changes: 7 additions & 6 deletions src/analysis/processing/qgsalgorithmrasterlayeruniquevalues.cpp
Expand Up @@ -16,6 +16,7 @@
***************************************************************************/

#include "qgsalgorithmrasterlayeruniquevalues.h"
#include "qgsstringutils.h"

///@cond PRIVATE

Expand Down Expand Up @@ -159,27 +160,27 @@ QVariantMap QgsRasterLayerUniqueValuesReportAlgorithm::processAlgorithm( const Q
QFile file( outputFile );
if ( file.open( QIODevice::WriteOnly | QIODevice::Text ) )
{
QString areaUnit = QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::distanceToAreaUnit( mCrs.mapUnits() ) );
const QString areaUnit = QgsStringUtils::ampersandEncode( QgsUnitTypes::toAbbreviatedString( QgsUnitTypes::distanceToAreaUnit( mCrs.mapUnits() ) ) );
double pixelArea = mRasterUnitsPerPixelX * mRasterUnitsPerPixelY;

QTextStream out( &file );
out << QString( "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/></head><body>\n" );
out << QString( "<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( "Analyzed file" ), mSource, QObject::tr( "band" ) ).arg( band );
out << QStringLiteral( "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\"/></head><body>\n" );
out << QStringLiteral( "<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( "Analyzed file" ), mSource, QObject::tr( "band" ) ).arg( band );
out << QObject::tr( "<p>%1: %2</p>\n" ).arg( QObject::tr( "Extent" ), mExtent.toString() );
out << QObject::tr( "<p>%1: %2 (%3)</p>\n" ).arg( QObject::tr( "Projection" ), mCrs.description(), mCrs.authid() );
out << QObject::tr( "<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( "Width in pixels" ) ).arg( mLayerWidth ).arg( QObject::tr( "units per pixel" ) ).arg( mRasterUnitsPerPixelX );
out << QObject::tr( "<p>%1: %2 (%3 %4)</p>\n" ).arg( QObject::tr( "Height in pixels" ) ).arg( mLayerHeight ).arg( QObject::tr( "units per pixel" ) ).arg( mRasterUnitsPerPixelY );
out << QObject::tr( "<p>%1: %2</p>\n" ).arg( QObject::tr( "Total pixel count" ) ).arg( layerSize );
if ( mHasNoDataValue )
out << QObject::tr( "<p>%1: %2</p>\n" ).arg( QObject::tr( "NODATA pixel count" ) ).arg( noDataCount );
out << QString( "<table><tr><td>%1</td><td>%2</td><td>%3 (%4)</td></tr>\n" ).arg( QObject::tr( "Value" ), QObject::tr( "Pixel count" ), QObject::tr( "Area" ), areaUnit );
out << QStringLiteral( "<table><tr><td>%1</td><td>%2</td><td>%3 (%4)</td></tr>\n" ).arg( QObject::tr( "Value" ), QObject::tr( "Pixel count" ), QObject::tr( "Area" ), areaUnit );

for ( auto it = sortedUniqueValues.constBegin(); it != sortedUniqueValues.constEnd(); ++it )
{
double area = it.value() * pixelArea;
out << QString( "<tr><td>%1</td><td>%2</td><td>%3</td></tr>\n" ).arg( it.key() ).arg( it.value() ).arg( QString::number( area, 'g', 16 ) );
out << QStringLiteral( "<tr><td>%1</td><td>%2</td><td>%3</td></tr>\n" ).arg( it.key() ).arg( it.value() ).arg( QString::number( area, 'g', 16 ) );
}
out << QString( "</table>\n</body></html>" );
out << QStringLiteral( "</table>\n</body></html>" );
outputs.insert( QStringLiteral( "OUTPUT_HTML_FILE" ), outputFile );
}
}
Expand Down
21 changes: 21 additions & 0 deletions src/core/qgsstringutils.cpp
Expand Up @@ -101,6 +101,27 @@ QString QgsStringUtils::capitalize( const QString &string, QgsStringUtils::Capit
return string;
}

// original code from http://www.qtcentre.org/threads/52456-HTML-Unicode-ampersand-encoding
QString QgsStringUtils::ampersandEncode( const QString &string )
{
QString encoded;
for ( int i = 0; i < string.size(); ++i )
{
QChar ch = string.at( i );
if ( ch.unicode() > 160 )
encoded += QStringLiteral( "&#%1;" ).arg( static_cast< int >( ch.unicode() ) );
else if ( ch.unicode() == 38 )
encoded += QStringLiteral( "&amp;" );
else if ( ch.unicode() == 60 )
encoded += QStringLiteral( "&lt;" );
else if ( ch.unicode() == 62 )
encoded += QStringLiteral( "&gt;" );
else
encoded += ch;
}
return encoded;
}

int QgsStringUtils::levenshteinDistance( const QString &string1, const QString &string2, bool caseSensitive )
{
int length1 = string1.length();
Expand Down
7 changes: 7 additions & 0 deletions src/core/qgsstringutils.h
Expand Up @@ -200,6 +200,13 @@ class CORE_EXPORT QgsStringUtils
*/
static QString capitalize( const QString &string, Capitalization capitalization );

/**
* Replaces any extended unicode characters with the XML style &#233; encoded versions
* of these characeters.
* \since QGIS 3.2
*/
static QString ampersandEncode( const QString &string );

/**
* Returns the Levenshtein edit distance between two strings. This equates to the minimum
* number of character edits (insertions, deletions or substitutions) required to change
Expand Down
22 changes: 22 additions & 0 deletions tests/src/core/testqgsstringutils.cpp
Expand Up @@ -36,6 +36,8 @@ class TestQgsStringUtils : public QObject
void insertLinks();
void titleCase_data();
void titleCase();
void ampersandEncode_data();
void ampersandEncode();

};

Expand Down Expand Up @@ -183,6 +185,26 @@ void TestQgsStringUtils::titleCase()
QCOMPARE( QgsStringUtils::capitalize( input, QgsStringUtils::TitleCase ), expected );
}

void TestQgsStringUtils::ampersandEncode_data()
{
QTest::addColumn<QString>( "input" );
QTest::addColumn<QString>( "expected" );

QTest::newRow( "empty string" ) << "" << "";
QTest::newRow( "amp" ) << "a & b" << "a &amp; b";
QTest::newRow( "gt" ) << "a > b" << "a &gt; b";
QTest::newRow( "lt" ) << "a < b" << "a &lt; b";
QTest::newRow( "mix" ) << "a <²> b" << "a &lt;&#178;&gt; b";
}

void TestQgsStringUtils::ampersandEncode()
{
QFETCH( QString, input );
QFETCH( QString, expected );
QCOMPARE( QgsStringUtils::ampersandEncode( input ), expected );

}


QGSTEST_MAIN( TestQgsStringUtils )
#include "testqgsstringutils.moc"

0 comments on commit f7a6864

Please sign in to comment.