Reduce duplicate code

This commit is contained in:
Nyall Dawson 2024-10-10 14:33:29 +10:00
parent 4c22dab199
commit d36982fd4d
12 changed files with 84 additions and 57 deletions

View File

@ -2,6 +2,7 @@
try: try:
QgsTextDocument.fromPlainText = staticmethod(QgsTextDocument.fromPlainText) QgsTextDocument.fromPlainText = staticmethod(QgsTextDocument.fromPlainText)
QgsTextDocument.fromHtml = staticmethod(QgsTextDocument.fromHtml) QgsTextDocument.fromHtml = staticmethod(QgsTextDocument.fromHtml)
QgsTextDocument.fromTextAndFormat = staticmethod(QgsTextDocument.fromTextAndFormat)
QgsTextDocument.__group__ = ['textrenderer'] QgsTextDocument.__group__ = ['textrenderer']
except NameError: except NameError:
pass pass

View File

@ -55,6 +55,15 @@ Constructor for QgsTextDocument consisting of a set of HTML formatted ``lines``.
If the HTML contains tab characters they will be appended as separate text fragments If the HTML contains tab characters they will be appended as separate text fragments
within the document, consisting of just the tab character. within the document, consisting of just the tab character.
%End
static QgsTextDocument fromTextAndFormat( const QStringList &lines, const QgsTextFormat &format );
%Docstring
Constructor for QgsTextDocument consisting of a set of ``lines``, respecting settings from a text ``format``.
This method will determine from the text ``format`` whether the lines should be treated as HTML or plain text.
.. versionadded:: 3.40
%End %End
void append( const QgsTextBlock &block ); void append( const QgsTextBlock &block );

View File

@ -2,6 +2,7 @@
try: try:
QgsTextDocument.fromPlainText = staticmethod(QgsTextDocument.fromPlainText) QgsTextDocument.fromPlainText = staticmethod(QgsTextDocument.fromPlainText)
QgsTextDocument.fromHtml = staticmethod(QgsTextDocument.fromHtml) QgsTextDocument.fromHtml = staticmethod(QgsTextDocument.fromHtml)
QgsTextDocument.fromTextAndFormat = staticmethod(QgsTextDocument.fromTextAndFormat)
QgsTextDocument.__group__ = ['textrenderer'] QgsTextDocument.__group__ = ['textrenderer']
except NameError: except NameError:
pass pass

View File

@ -55,6 +55,15 @@ Constructor for QgsTextDocument consisting of a set of HTML formatted ``lines``.
If the HTML contains tab characters they will be appended as separate text fragments If the HTML contains tab characters they will be appended as separate text fragments
within the document, consisting of just the tab character. within the document, consisting of just the tab character.
%End
static QgsTextDocument fromTextAndFormat( const QStringList &lines, const QgsTextFormat &format );
%Docstring
Constructor for QgsTextDocument consisting of a set of ``lines``, respecting settings from a text ``format``.
This method will determine from the text ``format`` whether the lines should be treated as HTML or plain text.
.. versionadded:: 3.40
%End %End
void append( const QgsTextBlock &block ); void append( const QgsTextBlock &block );

View File

@ -306,18 +306,7 @@ void QgsDecorationGrid::drawCoordinateAnnotation( QgsRenderContext &context, QPo
const QFontMetricsF textMetrics = QgsTextRenderer::fontMetrics( context, mTextFormat ); const QFontMetricsF textMetrics = QgsTextRenderer::fontMetrics( context, mTextFormat );
const double textDescent = textMetrics.descent(); const double textDescent = textMetrics.descent();
QgsTextDocument doc; const QgsTextDocument doc = QgsTextDocument::fromTextAndFormat( annotationStringList, mTextFormat );
if ( !mTextFormat.allowHtmlFormatting() )
{
doc = QgsTextDocument::fromPlainText( annotationStringList );
}
else
{
doc = QgsTextDocument::fromHtml( annotationStringList );
}
if ( doc.size() == 0 )
return;
doc.applyCapitalization( mTextFormat.capitalization() );
const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( doc, mTextFormat, context ); const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( doc, mTextFormat, context );
const QSizeF textSize = metrics.documentSize( Qgis::TextLayoutMode::Point, mTextFormat.orientation() ); const QSizeF textSize = metrics.documentSize( Qgis::TextLayoutMode::Point, mTextFormat.orientation() );

View File

@ -2158,14 +2158,7 @@ std::unique_ptr<QgsLabelFeature> QgsPalLayerSettings::registerFeatureWithDetails
case Qgis::LabelPlacement::OutsidePolygons: case Qgis::LabelPlacement::OutsidePolygons:
{ {
// non-curved labels always require document and metrics // non-curved labels always require document and metrics
if ( evaluatedFormat.allowHtmlFormatting() && !labelText.isEmpty() ) doc = QgsTextDocument::fromTextAndFormat( {labelText }, evaluatedFormat );
{
doc = QgsTextDocument::fromHtml( QStringList() << labelText );
}
else
{
doc = QgsTextDocument::fromPlainText( { labelText } );
}
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, &evaluatedFormat, &doc, &documentMetrics, &outerBounds ); calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, &evaluatedFormat, &doc, &documentMetrics, &outerBounds );
break; break;
} }

View File

@ -90,7 +90,7 @@ QgsLayerTreeModelLegendNode::ItemMetrics QgsLayerTreeModelLegendNode::draw( cons
const QStringList lines = settings.evaluateItemText( data( Qt::DisplayRole ).toString(), ctx->context->expressionContext() ); const QStringList lines = settings.evaluateItemText( data( Qt::DisplayRole ).toString(), ctx->context->expressionContext() );
const QgsTextDocument textDocument = f.allowHtmlFormatting() ? QgsTextDocument::fromHtml( lines ) : QgsTextDocument::fromPlainText( lines ); const QgsTextDocument textDocument = QgsTextDocument::fromTextAndFormat( lines, f );
// cppcheck-suppress autoVariables // cppcheck-suppress autoVariables
ctx->textDocument = &textDocument; ctx->textDocument = &textDocument;
@ -202,7 +202,7 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings &set
if ( !document ) if ( !document )
{ {
const QStringList lines = settings.evaluateItemText( data( Qt::DisplayRole ).toString(), context->expressionContext() ); const QStringList lines = settings.evaluateItemText( data( Qt::DisplayRole ).toString(), context->expressionContext() );
tempDocument.emplace( format.allowHtmlFormatting() ? QgsTextDocument::fromHtml( lines ) : QgsTextDocument::fromPlainText( lines ) ); tempDocument.emplace( QgsTextDocument::fromTextAndFormat( lines, format ) );
document = &tempDocument.value(); document = &tempDocument.value();
} }

View File

@ -69,15 +69,7 @@ class QgsLinearReferencingSymbolLayerLabelProvider final : public QgsAbstractLab
QgsPoint mapPoint( painterPoint ); QgsPoint mapPoint( painterPoint );
mapPoint.transform( context.mapToPixel().transform().inverted() ); mapPoint.transform( context.mapToPixel().transform().inverted() );
QgsTextDocument doc; const QgsTextDocument doc = QgsTextDocument::fromTextAndFormat( { text }, format );
if ( format.allowHtmlFormatting() && !text.isEmpty() )
{
doc = QgsTextDocument::fromHtml( QStringList() << text );
}
else
{
doc = QgsTextDocument::fromPlainText( { text } );
}
QgsTextDocumentMetrics documentMetrics = QgsTextDocumentMetrics::calculateMetrics( doc, format, context ); QgsTextDocumentMetrics documentMetrics = QgsTextDocumentMetrics::calculateMetrics( doc, format, context );
const QSizeF size = documentMetrics.documentSize( Qgis::TextLayoutMode::Point, Qgis::TextOrientation::Horizontal ); const QSizeF size = documentMetrics.documentSize( Qgis::TextLayoutMode::Point, Qgis::TextOrientation::Horizontal );

View File

@ -18,6 +18,7 @@
#include "qgsstringutils.h" #include "qgsstringutils.h"
#include "qgstextblock.h" #include "qgstextblock.h"
#include "qgstextfragment.h" #include "qgstextfragment.h"
#include "qgstextformat.h"
#include <QTextDocument> #include <QTextDocument>
#include <QTextBlock> #include <QTextBlock>
@ -244,6 +245,22 @@ QgsTextDocument QgsTextDocument::fromHtml( const QStringList &lines )
return document; return document;
} }
QgsTextDocument QgsTextDocument::fromTextAndFormat( const QStringList &lines, const QgsTextFormat &format )
{
QgsTextDocument doc;
if ( !format.allowHtmlFormatting() || lines.isEmpty() )
{
doc = QgsTextDocument::fromPlainText( lines );
}
else
{
doc = QgsTextDocument::fromHtml( lines );
}
if ( doc.size() > 0 )
doc.applyCapitalization( format.capitalization() );
return doc;
}
void QgsTextDocument::append( const QgsTextBlock &block ) void QgsTextDocument::append( const QgsTextBlock &block )
{ {
mBlocks.append( block ); mBlocks.append( block );

View File

@ -71,6 +71,15 @@ class CORE_EXPORT QgsTextDocument
*/ */
static QgsTextDocument fromHtml( const QStringList &lines ); static QgsTextDocument fromHtml( const QStringList &lines );
/**
* Constructor for QgsTextDocument consisting of a set of \a lines, respecting settings from a text \a format.
*
* This method will determine from the text \a format whether the lines should be treated as HTML or plain text.
*
* \since QGIS 3.40
*/
static QgsTextDocument fromTextAndFormat( const QStringList &lines, const QgsTextFormat &format );
/** /**
* Appends a \a block to the document. * Appends a \a block to the document.
*/ */

View File

@ -84,8 +84,7 @@ void QgsTextRenderer::drawText( const QRectF &rect, double rotation, Qgis::TextH
documentContext.setFlags( flags ); documentContext.setFlags( flags );
documentContext.setMaximumWidth( rect.width() ); documentContext.setMaximumWidth( rect.width() );
QgsTextDocument document = lFormat.allowHtmlFormatting() ? QgsTextDocument::fromHtml( text ) : QgsTextDocument::fromPlainText( text ); const QgsTextDocument document = QgsTextDocument::fromTextAndFormat( text, lFormat );
document.applyCapitalization( lFormat.capitalization() );
const double fontScale = calculateScaleFactorForFormat( context, lFormat ); const double fontScale = calculateScaleFactorForFormat( context, lFormat );
const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( document, lFormat, context, fontScale, documentContext ); const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( document, lFormat, context, fontScale, documentContext );
@ -118,8 +117,7 @@ void QgsTextRenderer::drawText( QPointF point, double rotation, Qgis::TextHorizo
lFormat = updateShadowPosition( lFormat ); lFormat = updateShadowPosition( lFormat );
// DO NOT USE _format in the following code, always use lFormat!! // DO NOT USE _format in the following code, always use lFormat!!
QgsTextDocument document = lFormat.allowHtmlFormatting() ? QgsTextDocument::fromHtml( textLines ) : QgsTextDocument::fromPlainText( textLines ); const QgsTextDocument document = QgsTextDocument::fromTextAndFormat( textLines, lFormat );
document.applyCapitalization( lFormat.capitalization() );
const double fontScale = calculateScaleFactorForFormat( context, lFormat ); const double fontScale = calculateScaleFactorForFormat( context, lFormat );
const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( document, lFormat, context, fontScale ); const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( document, lFormat, context, fontScale );
@ -151,8 +149,7 @@ void QgsTextRenderer::drawTextOnLine( const QPolygonF &line, const QString &text
// DO NOT USE _format in the following code, always use lFormat!! // DO NOT USE _format in the following code, always use lFormat!!
// todo handle newlines?? // todo handle newlines??
QgsTextDocument document = lFormat.allowHtmlFormatting() ? QgsTextDocument::fromHtml( { text } ) : QgsTextDocument::fromPlainText( { text } ); const QgsTextDocument document = QgsTextDocument::fromTextAndFormat( {text}, lFormat );
document.applyCapitalization( lFormat.capitalization() );
drawDocumentOnLine( line, lFormat, document, context, offsetAlongLine, offsetFromLine ); drawDocumentOnLine( line, lFormat, document, context, offsetAlongLine, offsetFromLine );
} }
@ -396,7 +393,7 @@ QgsTextFormat QgsTextRenderer::updateShadowPosition( const QgsTextFormat &format
void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, Qgis::TextHorizontalAlignment alignment, void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, Qgis::TextHorizontalAlignment alignment,
const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, Qgis::TextComponent part, bool ) const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, Qgis::TextComponent part, bool )
{ {
const QgsTextDocument document = format.allowHtmlFormatting() ? QgsTextDocument::fromHtml( textLines ) : QgsTextDocument::fromPlainText( textLines ); const QgsTextDocument document = QgsTextDocument::fromTextAndFormat( textLines, format );
const double fontScale = calculateScaleFactorForFormat( context, format ); const double fontScale = calculateScaleFactorForFormat( context, format );
const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( document, format, context, fontScale ); const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( document, format, context, fontScale );
@ -478,7 +475,7 @@ void QgsTextRenderer::drawPart( const QRectF &rect, double rotation, Qgis::TextH
void QgsTextRenderer::drawPart( QPointF origin, double rotation, Qgis::TextHorizontalAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, Qgis::TextComponent part, bool ) void QgsTextRenderer::drawPart( QPointF origin, double rotation, Qgis::TextHorizontalAlignment alignment, const QStringList &textLines, QgsRenderContext &context, const QgsTextFormat &format, Qgis::TextComponent part, bool )
{ {
const QgsTextDocument document = format.allowHtmlFormatting() ? QgsTextDocument::fromHtml( textLines ) : QgsTextDocument::fromPlainText( textLines ); const QgsTextDocument document = QgsTextDocument::fromTextAndFormat( textLines, format );
const double fontScale = calculateScaleFactorForFormat( context, format ); const double fontScale = calculateScaleFactorForFormat( context, format );
const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( document, format, context, fontScale ); const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( document, format, context, fontScale );
@ -815,19 +812,10 @@ void QgsTextRenderer::drawMask( QgsRenderContext &context, const QgsTextRenderer
double QgsTextRenderer::textWidth( const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, QFontMetricsF * ) double QgsTextRenderer::textWidth( const QgsRenderContext &context, const QgsTextFormat &format, const QStringList &textLines, QFontMetricsF * )
{ {
QgsTextDocument doc; const QgsTextDocument doc = QgsTextDocument::fromTextAndFormat( textLines, format );
if ( !format.allowHtmlFormatting() )
{
doc = QgsTextDocument::fromPlainText( textLines );
}
else
{
doc = QgsTextDocument::fromHtml( textLines );
}
if ( doc.size() == 0 ) if ( doc.size() == 0 )
return 0; return 0;
doc.applyCapitalization( format.capitalization() );
return textWidth( context, format, doc ); return textWidth( context, format, doc );
} }
@ -857,14 +845,8 @@ double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTe
} }
} }
if ( !format.allowHtmlFormatting() ) const QgsTextDocument doc = QgsTextDocument::fromTextAndFormat( lines, format );
{ return textHeight( context, format, doc, mode );
return textHeight( context, format, QgsTextDocument::fromPlainText( lines ), mode );
}
else
{
return textHeight( context, format, QgsTextDocument::fromHtml( lines ), mode );
}
} }
double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTextFormat &format, QChar character, bool includeEffects ) double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTextFormat &format, QChar character, bool includeEffects )

View File

@ -20,6 +20,7 @@ from qgis.core import (
QgsTextCharacterFormat, QgsTextCharacterFormat,
QgsTextDocument, QgsTextDocument,
QgsTextFragment, QgsTextFragment,
QgsTextFormat
) )
import unittest import unittest
from qgis.testing import start_app, QgisTestCase from qgis.testing import start_app, QgisTestCase
@ -199,6 +200,30 @@ class TestQgsTextDocument(QgisTestCase):
self.assertTrue(doc[1][1].isTab()) self.assertTrue(doc[1][1].isTab())
self.assertEqual(doc[1][2].text(), 'cdcd') self.assertEqual(doc[1][2].text(), 'cdcd')
def testFromTextAndFormat(self):
format = QgsTextFormat()
format.setAllowHtmlFormatting(False)
doc = QgsTextDocument.fromTextAndFormat(['abc <b>def</b>'], format)
self.assertEqual(len(doc), 1)
self.assertEqual(len(doc[0]), 1)
self.assertEqual(doc[0][0].text(), 'abc <b>def</b>')
# as html
format.setAllowHtmlFormatting(True)
doc = QgsTextDocument.fromTextAndFormat(['abc <b>def</b>'], format)
self.assertEqual(len(doc), 1)
self.assertEqual(len(doc[0]), 2)
self.assertEqual(doc[0][0].text(), 'abc ')
self.assertEqual(doc[0][1].text(), 'def')
# with capitalization option
format.setCapitalization(Qgis.Capitalization.AllUppercase)
format.setAllowHtmlFormatting(False)
doc = QgsTextDocument.fromTextAndFormat(['abc def'], format)
self.assertEqual(len(doc), 1)
self.assertEqual(len(doc[0]), 1)
self.assertEqual(doc[0][0].text(), 'ABC DEF')
def testFromHtmlVerticalAlignment(self): def testFromHtmlVerticalAlignment(self):
doc = QgsTextDocument.fromHtml(['abc<div style="color: red"><sub>def<b>extra</b></sub> ghi</div><sup>sup</sup><span style="vertical-align: sub">css</span>']) doc = QgsTextDocument.fromHtml(['abc<div style="color: red"><sub>def<b>extra</b></sub> ghi</div><sup>sup</sup><span style="vertical-align: sub">css</span>'])
self.assertEqual(len(doc), 3) self.assertEqual(len(doc), 3)