Adapt QgsPalLabeling.splitToLines to account for HTML formatting

This commit is contained in:
Nyall Dawson 2020-05-08 13:34:11 +10:00
parent 87296f246c
commit f5d68ff423
5 changed files with 51 additions and 23 deletions

View File

@ -783,7 +783,7 @@ Checks whether a geometry requires preparation before registration with PAL
.. versionadded:: 2.9
%End
static QStringList splitToLines( const QString &text, const QString &wrapCharacter, int autoWrapLength = 0, bool useMaxLineLengthWhenAutoWrapping = true );
static QStringList splitToLines( const QString &text, const QString &wrapCharacter, int autoWrapLength = 0, bool useMaxLineLengthWhenAutoWrapping = true, bool allowHtmlFormatting = false );
%Docstring
Splits a ``text`` string to a list of separate lines, using a specified wrap character (``wrapCharacter``).
The text string will be split on either newline characters or the wrap character.

View File

@ -1393,6 +1393,8 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QSt
}
QgsRenderContext *rc = context ? context : scopedRc.get();
const bool htmlFormatting = mFormat.allowHtmlFormatting();
QString wrapchr = wrapChar;
int evalAutoWrapLength = autoWrapLength;
double multilineH = mFormat.lineHeight();
@ -1531,7 +1533,7 @@ void QgsPalLayerSettings::calculateLabelSize( const QFontMetricsF *fm, const QSt
double w = 0.0, h = 0.0, rw = 0.0, rh = 0.0;
double labelHeight = fm->ascent() + fm->descent(); // ignore +1 for baseline
const QStringList multiLineSplit = QgsPalLabeling::splitToLines( textCopy, wrapchr, evalAutoWrapLength, useMaxLineLengthForAutoWrap );
const QStringList multiLineSplit = QgsPalLabeling::splitToLines( textCopy, wrapchr, evalAutoWrapLength, useMaxLineLengthForAutoWrap, htmlFormatting );
int lines = multiLineSplit.size();
switch ( orientation )
@ -3548,33 +3550,49 @@ bool QgsPalLabeling::geometryRequiresPreparation( const QgsGeometry &geometry, Q
return false;
}
QStringList QgsPalLabeling::splitToLines( const QString &text, const QString &wrapCharacter, const int autoWrapLength, const bool useMaxLineLengthWhenAutoWrapping )
QStringList QgsPalLabeling::splitToLines( const QString &text, const QString &wrapCharacter, const int autoWrapLength, const bool useMaxLineLengthWhenAutoWrapping, const bool allowHtmlFormatting )
{
QStringList multiLineSplit;
auto splitLine = [ & ]( const QString & input )
{
QStringList thisParts;
if ( !wrapCharacter.isEmpty() && wrapCharacter != QLatin1String( "\n" ) )
{
//wrap on both the wrapchr and new line characters
const QStringList lines = text.split( wrapCharacter );
const QStringList lines = input.split( wrapCharacter );
for ( const QString &line : lines )
{
multiLineSplit.append( line.split( '\n' ) );
thisParts.append( line.split( '\n' ) );
}
}
else
{
multiLineSplit = text.split( '\n' );
thisParts = input.split( '\n' );
}
// apply auto wrapping to each manually created line
if ( autoWrapLength != 0 )
{
QStringList autoWrappedLines;
autoWrappedLines.reserve( multiLineSplit.count() );
for ( const QString &line : qgis::as_const( multiLineSplit ) )
autoWrappedLines.reserve( thisParts.count() );
for ( const QString &line : qgis::as_const( thisParts ) )
{
autoWrappedLines.append( QgsStringUtils::wordWrap( line, autoWrapLength, useMaxLineLengthWhenAutoWrapping ).split( '\n' ) );
}
multiLineSplit = autoWrappedLines;
thisParts = autoWrappedLines;
}
multiLineSplit.append( thisParts );
};
if ( allowHtmlFormatting )
{
const QStringList htmlBlocks = QgsTextRenderer::extractTextBlocksFromHtml( text );
for ( const QString &block : htmlBlocks )
splitLine( block );
}
else
{
splitLine( text );
}
return multiLineSplit;
}

View File

@ -1301,7 +1301,7 @@ class CORE_EXPORT QgsPalLabeling
*
* \since QGIS 2.9
*/
static QStringList splitToLines( const QString &text, const QString &wrapCharacter, int autoWrapLength = 0, bool useMaxLineLengthWhenAutoWrapping = true );
static QStringList splitToLines( const QString &text, const QString &wrapCharacter, int autoWrapLength = 0, bool useMaxLineLengthWhenAutoWrapping = true, bool allowHtmlFormatting = false );
/**
* Splits a text string to a list of graphemes, which are the smallest allowable character

View File

@ -611,7 +611,7 @@ void QgsVectorLayerLabelProvider::drawLabelPrivate( pal::LabelPosition *label, Q
}
//QgsDebugMsgLevel( "drawLabel " + txt, 4 );
QStringList multiLineList = QgsPalLabeling::splitToLines( txt, tmpLyr.wrapChar, tmpLyr.autoWrapLength, tmpLyr.useMaxLineLengthForAutoWrap );
QStringList multiLineList = QgsPalLabeling::splitToLines( txt, tmpLyr.wrapChar, tmpLyr.autoWrapLength, tmpLyr.useMaxLineLengthForAutoWrap, tmpLyr.format().allowHtmlFormatting() );
QgsTextRenderer::HAlignment hAlign = QgsTextRenderer::AlignLeft;
if ( tmpLyr.multilineAlign == QgsPalLayerSettings::MultiCenter )

View File

@ -356,6 +356,16 @@ class TestQgsPalLabeling(unittest.TestCase):
"""Intended to be overridden in subclasses"""
pass
def testSplitToLines(self):
self.assertEqual(QgsPalLabeling.splitToLines('', ''), [''])
self.assertEqual(QgsPalLabeling.splitToLines('abc def', ''), ['abc def'])
self.assertEqual(QgsPalLabeling.splitToLines('abc def', ' '), ['abc', 'def'])
self.assertEqual(QgsPalLabeling.splitToLines('abc\ndef', ' '), ['abc', 'def'])
self.assertEqual(QgsPalLabeling.splitToLines('abc def', ' ', allowHtmlFormatting=True), ['abc', 'def'])
self.assertEqual(QgsPalLabeling.splitToLines('<span style="color: red">R_ED</span> not <div>red</div>', ' ', allowHtmlFormatting=True), ['R_ED', 'not', '', 'red'])
self.assertEqual(QgsPalLabeling.splitToLines('<span style="color: red">R_ED</span> not <div>red</div>', '_',
allowHtmlFormatting=True), ['R', 'ED not ', 'red'])
class TestPALConfig(TestQgsPalLabeling):