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:
QgsTextDocument.fromPlainText = staticmethod(QgsTextDocument.fromPlainText)
QgsTextDocument.fromHtml = staticmethod(QgsTextDocument.fromHtml)
QgsTextDocument.fromTextAndFormat = staticmethod(QgsTextDocument.fromTextAndFormat)
QgsTextDocument.__group__ = ['textrenderer']
except NameError:
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
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
void append( const QgsTextBlock &block );

View File

@ -2,6 +2,7 @@
try:
QgsTextDocument.fromPlainText = staticmethod(QgsTextDocument.fromPlainText)
QgsTextDocument.fromHtml = staticmethod(QgsTextDocument.fromHtml)
QgsTextDocument.fromTextAndFormat = staticmethod(QgsTextDocument.fromTextAndFormat)
QgsTextDocument.__group__ = ['textrenderer']
except NameError:
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
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
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 double textDescent = textMetrics.descent();
QgsTextDocument doc;
if ( !mTextFormat.allowHtmlFormatting() )
{
doc = QgsTextDocument::fromPlainText( annotationStringList );
}
else
{
doc = QgsTextDocument::fromHtml( annotationStringList );
}
if ( doc.size() == 0 )
return;
doc.applyCapitalization( mTextFormat.capitalization() );
const QgsTextDocument doc = QgsTextDocument::fromTextAndFormat( annotationStringList, mTextFormat );
const QgsTextDocumentMetrics metrics = QgsTextDocumentMetrics::calculateMetrics( doc, mTextFormat, context );
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:
{
// non-curved labels always require document and metrics
if ( evaluatedFormat.allowHtmlFormatting() && !labelText.isEmpty() )
{
doc = QgsTextDocument::fromHtml( QStringList() << labelText );
}
else
{
doc = QgsTextDocument::fromPlainText( { labelText } );
}
doc = QgsTextDocument::fromTextAndFormat( {labelText }, evaluatedFormat );
calculateLabelSize( labelFontMetrics.get(), labelText, labelWidth, labelHeight, mCurFeat, &context, &rotatedLabelX, &rotatedLabelY, &evaluatedFormat, &doc, &documentMetrics, &outerBounds );
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 QgsTextDocument textDocument = f.allowHtmlFormatting() ? QgsTextDocument::fromHtml( lines ) : QgsTextDocument::fromPlainText( lines );
const QgsTextDocument textDocument = QgsTextDocument::fromTextAndFormat( lines, f );
// cppcheck-suppress autoVariables
ctx->textDocument = &textDocument;
@ -202,7 +202,7 @@ QSizeF QgsLayerTreeModelLegendNode::drawSymbolText( const QgsLegendSettings &set
if ( !document )
{
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();
}

View File

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

View File

@ -18,6 +18,7 @@
#include "qgsstringutils.h"
#include "qgstextblock.h"
#include "qgstextfragment.h"
#include "qgstextformat.h"
#include <QTextDocument>
#include <QTextBlock>
@ -244,6 +245,22 @@ QgsTextDocument QgsTextDocument::fromHtml( const QStringList &lines )
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 )
{
mBlocks.append( block );

View File

@ -71,6 +71,15 @@ class CORE_EXPORT QgsTextDocument
*/
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.
*/

View File

@ -84,8 +84,7 @@ void QgsTextRenderer::drawText( const QRectF &rect, double rotation, Qgis::TextH
documentContext.setFlags( flags );
documentContext.setMaximumWidth( rect.width() );
QgsTextDocument document = lFormat.allowHtmlFormatting() ? QgsTextDocument::fromHtml( text ) : QgsTextDocument::fromPlainText( text );
document.applyCapitalization( lFormat.capitalization() );
const QgsTextDocument document = QgsTextDocument::fromTextAndFormat( text, lFormat );
const double fontScale = calculateScaleFactorForFormat( context, lFormat );
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 );
// DO NOT USE _format in the following code, always use lFormat!!
QgsTextDocument document = lFormat.allowHtmlFormatting() ? QgsTextDocument::fromHtml( textLines ) : QgsTextDocument::fromPlainText( textLines );
document.applyCapitalization( lFormat.capitalization() );
const QgsTextDocument document = QgsTextDocument::fromTextAndFormat( textLines, lFormat );
const double fontScale = calculateScaleFactorForFormat( context, lFormat );
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!!
// todo handle newlines??
QgsTextDocument document = lFormat.allowHtmlFormatting() ? QgsTextDocument::fromHtml( { text } ) : QgsTextDocument::fromPlainText( { text } );
document.applyCapitalization( lFormat.capitalization() );
const QgsTextDocument document = QgsTextDocument::fromTextAndFormat( {text}, lFormat );
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,
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 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 )
{
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 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 * )
{
QgsTextDocument doc;
if ( !format.allowHtmlFormatting() )
{
doc = QgsTextDocument::fromPlainText( textLines );
}
else
{
doc = QgsTextDocument::fromHtml( textLines );
}
const QgsTextDocument doc = QgsTextDocument::fromTextAndFormat( textLines, format );
if ( doc.size() == 0 )
return 0;
doc.applyCapitalization( format.capitalization() );
return textWidth( context, format, doc );
}
@ -857,14 +845,8 @@ double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTe
}
}
if ( !format.allowHtmlFormatting() )
{
return textHeight( context, format, QgsTextDocument::fromPlainText( lines ), mode );
}
else
{
return textHeight( context, format, QgsTextDocument::fromHtml( lines ), mode );
}
const QgsTextDocument doc = QgsTextDocument::fromTextAndFormat( lines, format );
return textHeight( context, format, doc, mode );
}
double QgsTextRenderer::textHeight( const QgsRenderContext &context, const QgsTextFormat &format, QChar character, bool includeEffects )

View File

@ -20,6 +20,7 @@ from qgis.core import (
QgsTextCharacterFormat,
QgsTextDocument,
QgsTextFragment,
QgsTextFormat
)
import unittest
from qgis.testing import start_app, QgisTestCase
@ -199,6 +200,30 @@ class TestQgsTextDocument(QgisTestCase):
self.assertTrue(doc[1][1].isTab())
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):
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)