[api] Add tab positions list for QgsTextFormat

Allows setting a list of custom tab stop distances, instead
of just a single distance
This commit is contained in:
Nyall Dawson 2024-10-29 08:42:59 +10:00
parent 2edfe3e51a
commit 7badf62596
21 changed files with 501 additions and 6 deletions

View File

@ -6,3 +6,7 @@ try:
QgsTextFormat.__group__ = ['textrenderer']
except NameError:
pass
try:
QgsTextFormat.Tab.__group__ = ['textrenderer']
except NameError:
pass

View File

@ -506,6 +506,12 @@ Sets the ``unit`` for the line height for text.
%Docstring
Returns the distance for tab stops.
.. note::
This value will be ignored if :py:func:`~QgsTextFormat.tabPositions` is non-empty.
.. seealso:: :py:func:`tabPositions`
.. seealso:: :py:func:`tabStopDistanceUnit`
.. seealso:: :py:func:`setTabStopDistance`
@ -515,13 +521,103 @@ Returns the distance for tab stops.
void setTabStopDistance( double distance );
%Docstring
Sets the ``distance`` for tab stops. The units are specified using :py:func:`~QgsTextFormat.setTabStopDistanceUnit`.
Sets the ``distance`` for tab stops.
The units are specified using :py:func:`~QgsTextFormat.setTabStopDistanceUnit`.
.. note::
This value will be ignored if :py:func:`~QgsTextFormat.tabPositions` is non-empty.
.. seealso:: :py:func:`tabPositions`
.. seealso:: :py:func:`tabStopDistance`
.. seealso:: :py:func:`setTabStopDistanceUnit`
.. versionadded:: 3.38
%End
class Tab
{
%Docstring(signature="appended")
Defines a tab position for a text format.
.. versionadded:: 3.42
%End
%TypeHeaderCode
#include "qgstextformat.h"
%End
public:
explicit Tab( double position );
%Docstring
Constructor for a Tab at the specified ``position``.
%End
void setPosition( double position );
%Docstring
Sets the tab position.
.. seealso:: :py:func:`position`
%End
double position() const;
%Docstring
Returns the tab position.
.. seealso:: :py:func:`setPosition`
%End
bool operator==( const QgsTextFormat::Tab &other ) const;
SIP_PYOBJECT __repr__();
%MethodCode
const QString str = QStringLiteral( "<QgsTextFormat.Tab: %1>" ).arg( sipCpp->position() );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
%End
};
QList< QgsTextFormat::Tab > tabPositions() const;
%Docstring
Returns the list of tab positions for tab stops.
The units are specified using :py:func:`~QgsTextFormat.tabStopDistanceUnit`.
.. note::
If non-empty, this list overrides any distance defined by :py:func:`~QgsTextFormat.tabStopDistance`.
.. seealso:: :py:func:`setTabPositions`
.. seealso:: :py:func:`tabStopDistance`
.. seealso:: :py:func:`tabStopDistanceUnit`
.. seealso:: :py:func:`setTabStopDistance`
.. versionadded:: 3.42
%End
void setTabPositions( const QList< QgsTextFormat::Tab > &positions );
%Docstring
Sets the list of tab ``positions`` for tab stops.
The units are specified using :py:func:`~QgsTextFormat.setTabStopDistanceUnit`.
.. note::
If non-empty, this list overrides any distance defined by :py:func:`~QgsTextFormat.setTabStopDistance`.
.. seealso:: :py:func:`tabPositions`
.. seealso:: :py:func:`setTabStopDistance`
.. seealso:: :py:func:`setTabStopDistanceUnit`
.. versionadded:: 3.42
%End
Qgis::RenderUnit tabStopDistanceUnit() const;
@ -530,6 +626,8 @@ Returns the units for the tab stop distance.
.. seealso:: :py:func:`tabStopDistance`
.. seealso:: :py:func:`tabPositions`
.. seealso:: :py:func:`setTabStopDistanceUnit`
.. versionadded:: 3.38
@ -541,6 +639,8 @@ Sets the ``unit`` used for the tab stop distance.
.. seealso:: :py:func:`setTabStopDistance`
.. seealso:: :py:func:`setTabPositions`
.. seealso:: :py:func:`tabStopDistanceUnit`
.. versionadded:: 3.38

View File

@ -6,3 +6,7 @@ try:
QgsTextFormat.__group__ = ['textrenderer']
except NameError:
pass
try:
QgsTextFormat.Tab.__group__ = ['textrenderer']
except NameError:
pass

View File

@ -506,6 +506,12 @@ Sets the ``unit`` for the line height for text.
%Docstring
Returns the distance for tab stops.
.. note::
This value will be ignored if :py:func:`~QgsTextFormat.tabPositions` is non-empty.
.. seealso:: :py:func:`tabPositions`
.. seealso:: :py:func:`tabStopDistanceUnit`
.. seealso:: :py:func:`setTabStopDistance`
@ -515,13 +521,103 @@ Returns the distance for tab stops.
void setTabStopDistance( double distance );
%Docstring
Sets the ``distance`` for tab stops. The units are specified using :py:func:`~QgsTextFormat.setTabStopDistanceUnit`.
Sets the ``distance`` for tab stops.
The units are specified using :py:func:`~QgsTextFormat.setTabStopDistanceUnit`.
.. note::
This value will be ignored if :py:func:`~QgsTextFormat.tabPositions` is non-empty.
.. seealso:: :py:func:`tabPositions`
.. seealso:: :py:func:`tabStopDistance`
.. seealso:: :py:func:`setTabStopDistanceUnit`
.. versionadded:: 3.38
%End
class Tab
{
%Docstring(signature="appended")
Defines a tab position for a text format.
.. versionadded:: 3.42
%End
%TypeHeaderCode
#include "qgstextformat.h"
%End
public:
explicit Tab( double position );
%Docstring
Constructor for a Tab at the specified ``position``.
%End
void setPosition( double position );
%Docstring
Sets the tab position.
.. seealso:: :py:func:`position`
%End
double position() const;
%Docstring
Returns the tab position.
.. seealso:: :py:func:`setPosition`
%End
bool operator==( const QgsTextFormat::Tab &other ) const;
SIP_PYOBJECT __repr__();
%MethodCode
const QString str = QStringLiteral( "<QgsTextFormat.Tab: %1>" ).arg( sipCpp->position() );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
%End
};
QList< QgsTextFormat::Tab > tabPositions() const;
%Docstring
Returns the list of tab positions for tab stops.
The units are specified using :py:func:`~QgsTextFormat.tabStopDistanceUnit`.
.. note::
If non-empty, this list overrides any distance defined by :py:func:`~QgsTextFormat.tabStopDistance`.
.. seealso:: :py:func:`setTabPositions`
.. seealso:: :py:func:`tabStopDistance`
.. seealso:: :py:func:`tabStopDistanceUnit`
.. seealso:: :py:func:`setTabStopDistance`
.. versionadded:: 3.42
%End
void setTabPositions( const QList< QgsTextFormat::Tab > &positions );
%Docstring
Sets the list of tab ``positions`` for tab stops.
The units are specified using :py:func:`~QgsTextFormat.setTabStopDistanceUnit`.
.. note::
If non-empty, this list overrides any distance defined by :py:func:`~QgsTextFormat.setTabStopDistance`.
.. seealso:: :py:func:`tabPositions`
.. seealso:: :py:func:`setTabStopDistance`
.. seealso:: :py:func:`setTabStopDistanceUnit`
.. versionadded:: 3.42
%End
Qgis::RenderUnit tabStopDistanceUnit() const;
@ -530,6 +626,8 @@ Returns the units for the tab stop distance.
.. seealso:: :py:func:`tabStopDistance`
.. seealso:: :py:func:`tabPositions`
.. seealso:: :py:func:`setTabStopDistanceUnit`
.. versionadded:: 3.38
@ -541,6 +639,8 @@ Sets the ``unit`` used for the tab stop distance.
.. seealso:: :py:func:`setTabStopDistance`
.. seealso:: :py:func:`setTabPositions`
.. seealso:: :py:func:`tabStopDistanceUnit`
.. versionadded:: 3.38

View File

@ -128,7 +128,7 @@ void QgsPalLayerSettings::initPropertyDefinitions()
{ static_cast< int >( QgsPalLayerSettings::Property::AutoWrapLength ), QgsPropertyDefinition( "AutoWrapLength", QObject::tr( "Automatic word wrap line length" ), QgsPropertyDefinition::IntegerPositive, origin ) },
{ static_cast< int >( QgsPalLayerSettings::Property::MultiLineHeight ), QgsPropertyDefinition( "MultiLineHeight", QObject::tr( "Line height" ), QgsPropertyDefinition::DoublePositive, origin ) },
{ static_cast< int >( QgsPalLayerSettings::Property::MultiLineAlignment ), QgsPropertyDefinition( "MultiLineAlignment", QgsPropertyDefinition::DataTypeString, QObject::tr( "Line alignment" ), QObject::tr( "string " ) + "[<b>Left</b>|<b>Center</b>|<b>Right</b>|<b>Follow</b>]", origin ) },
{ static_cast< int >( QgsPalLayerSettings::Property::TabStopDistance ), QgsPropertyDefinition( "TabStopDistance", QObject::tr( "Tab stop distance" ), QgsPropertyDefinition::DoublePositive, origin ) },
{ static_cast< int >( QgsPalLayerSettings::Property::TabStopDistance ), QgsPropertyDefinition( "TabStopDistance", QgsPropertyDefinition::DataTypeNumeric, QObject::tr( "Tab stop distance(s)" ), QObject::tr( "Numeric distance or array of distances" ), origin ) },
{ static_cast< int >( QgsPalLayerSettings::Property::TextOrientation ), QgsPropertyDefinition( "TextOrientation", QgsPropertyDefinition::DataTypeString, QObject::tr( "Text orientation" ), QObject::tr( "string " ) + "[<b>horizontal</b>|<b>vertical</b>]", origin ) },
{ static_cast< int >( QgsPalLayerSettings::Property::DirSymbDraw ), QgsPropertyDefinition( "DirSymbDraw", QObject::tr( "Draw direction symbol" ), QgsPropertyDefinition::Boolean, origin ) },
{ static_cast< int >( QgsPalLayerSettings::Property::DirSymbLeft ), QgsPropertyDefinition( "DirSymbLeft", QObject::tr( "Left direction symbol" ), QgsPropertyDefinition::String, origin ) },

View File

@ -33,6 +33,7 @@ constexpr double SUBSCRIPT_VERTICAL_BASELINE_ADJUSTMENT_FACTOR = 1.0 / 6.0;
struct DocumentMetrics
{
double tabStopDistancePainterUnits = 0;
QList< double > tabStopDistancesPainterUnits;
double width = 0;
double heightLabelMode = 0;
double heightPointRectMode = 0;
@ -260,7 +261,24 @@ void QgsTextDocumentMetrics::processFragment( QgsTextDocumentMetrics &res, const
if ( fragment.isTab() )
{
// special handling for tab characters
const double nextTabStop = ( std::floor( thisBlockMetrics.blockXMax / documentMetrics.tabStopDistancePainterUnits ) + 1 ) * documentMetrics.tabStopDistancePainterUnits;
double nextTabStop = 0;
if ( !documentMetrics.tabStopDistancesPainterUnits.isEmpty() )
{
// if we don't find a tab stop before the current length of line, we just ignore the tab character entirely
nextTabStop = thisBlockMetrics.blockXMax;
for ( const double tabStop : std::as_const( documentMetrics.tabStopDistancesPainterUnits ) )
{
if ( tabStop >= thisBlockMetrics.blockXMax )
{
nextTabStop = tabStop;
break;
}
}
}
else
{
nextTabStop = ( std::floor( thisBlockMetrics.blockXMax / documentMetrics.tabStopDistancePainterUnits ) + 1 ) * documentMetrics.tabStopDistancePainterUnits;
}
const double fragmentWidth = nextTabStop - thisBlockMetrics.blockXMax;
thisBlockMetrics.blockWidth += fragmentWidth;
@ -578,6 +596,17 @@ QgsTextDocumentMetrics QgsTextDocumentMetrics::calculateMetrics( const QgsTextDo
? format.tabStopDistance() * font.pixelSize() / scaleFactor
: context.convertToPainterUnits( format.tabStopDistance(), format.tabStopDistanceUnit(), format.tabStopDistanceMapUnitScale() );
const QList< QgsTextFormat::Tab > tabPositions = format.tabPositions();
documentMetrics.tabStopDistancesPainterUnits.reserve( tabPositions.size() );
for ( const QgsTextFormat::Tab &tab : tabPositions )
{
documentMetrics.tabStopDistancesPainterUnits.append(
format.tabStopDistanceUnit() == Qgis::RenderUnit::Percentage
? tab.position() * font.pixelSize() / scaleFactor
: context.convertToPainterUnits( tab.position(), format.tabStopDistanceUnit(), format.tabStopDistanceMapUnitScale() )
);
}
documentMetrics.blockSize = document.size();
res.mDocument.reserve( documentMetrics.blockSize );
res.mFragmentFonts.reserve( documentMetrics.blockSize );

View File

@ -87,6 +87,7 @@ bool QgsTextFormat::operator==( const QgsTextFormat &other ) const
|| d->forcedItalic != other.forcedItalic()
|| d->capitalization != other.capitalization()
|| d->tabStopDistance != other.tabStopDistance()
|| d->tabPositions != other.tabPositions()
|| d->tabStopDistanceUnits != other.tabStopDistanceUnit()
|| d->tabStopDistanceMapUnitScale != other.tabStopDistanceMapUnitScale()
|| mBufferSettings != other.mBufferSettings
@ -389,6 +390,17 @@ void QgsTextFormat::setTabStopDistance( double distance )
d->tabStopDistance = distance;
}
QList<QgsTextFormat::Tab> QgsTextFormat::tabPositions() const
{
return d->tabPositions;
}
void QgsTextFormat::setTabPositions( const QList<Tab> &positions )
{
d->isValid = true;
d->tabPositions = positions;
}
Qgis::RenderUnit QgsTextFormat::tabStopDistanceUnit() const
{
return d->tabStopDistanceUnits;
@ -689,6 +701,19 @@ void QgsTextFormat::readXml( const QDomElement &elem, const QgsReadWriteContext
d->tabStopDistanceUnits = QgsUnitTypes::decodeRenderUnit( textStyleElem.attribute( QStringLiteral( "tabStopDistanceUnit" ), QStringLiteral( "Point" ) ), &ok );
d->tabStopDistanceMapUnitScale = QgsSymbolLayerUtils::decodeMapUnitScale( textStyleElem.attribute( QStringLiteral( "tabStopDistanceMapUnitScale" ) ) );
QList< Tab > tabPositions;
{
const QDomElement tabPositionsElem = textStyleElem.firstChildElement( QStringLiteral( "tabPositions" ) );
const QDomNodeList tabNodes = tabPositionsElem.childNodes();
tabPositions.reserve( tabNodes.size() );
for ( int i = 0; i < tabNodes.count(); ++i )
{
const QDomElement tabElem = tabNodes.at( i ).toElement();
tabPositions << Tab( tabElem.attribute( QStringLiteral( "position" ) ).toDouble() );
}
}
d->tabPositions = tabPositions;
if ( textStyleElem.hasAttribute( QStringLiteral( "capitalization" ) ) )
d->capitalization = static_cast< Qgis::Capitalization >( textStyleElem.attribute( QStringLiteral( "capitalization" ), QString::number( static_cast< int >( Qgis::Capitalization::MixedCase ) ) ).toInt() );
else
@ -792,6 +817,18 @@ QDomElement QgsTextFormat::writeXml( QDomDocument &doc, const QgsReadWriteContex
textStyleElem.setAttribute( QStringLiteral( "tabStopDistanceUnit" ), QgsUnitTypes::encodeUnit( d->tabStopDistanceUnits ) );
textStyleElem.setAttribute( QStringLiteral( "tabStopDistanceMapUnitScale" ), QgsSymbolLayerUtils::encodeMapUnitScale( d->tabStopDistanceMapUnitScale ) );
if ( !d->tabPositions.empty() )
{
QDomElement tabPositionsElem = doc.createElement( QStringLiteral( "tabPositions" ) );
for ( const Tab &tab : std::as_const( d->tabPositions ) )
{
QDomElement tabElem = doc.createElement( QStringLiteral( "tab" ) );
tabElem.setAttribute( QStringLiteral( "position" ), tab.position() );
tabPositionsElem.appendChild( tabElem );
}
textStyleElem.appendChild( tabPositionsElem );
}
textStyleElem.setAttribute( QStringLiteral( "allowHtml" ), d->allowHtmlFormatting ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
textStyleElem.setAttribute( QStringLiteral( "capitalization" ), QString::number( static_cast< int >( d->capitalization ) ) );
@ -1144,7 +1181,31 @@ void QgsTextFormat::updateDataDefinedProperties( QgsRenderContext &context )
const QVariant val = d->mDataDefinedProperties.value( QgsPalLayerSettings::Property::TabStopDistance, context.expressionContext(), d->tabStopDistance );
if ( !QgsVariantUtils::isNull( val ) )
{
d->tabStopDistance = val.toDouble();
if ( val.userType() == QMetaType::Type::QVariantList )
{
const QVariantList parts = val.toList();
d->tabPositions.clear();
d->tabPositions.reserve( parts.size() );
for ( const QVariant &part : parts )
{
d->tabPositions.append( Tab( part.toDouble() ) );
}
}
else if ( val.userType() == QMetaType::Type::QStringList )
{
const QStringList parts = val.toStringList();
d->tabPositions.clear();
d->tabPositions.reserve( parts.size() );
for ( const QString &part : parts )
{
d->tabPositions.append( Tab( part.toDouble() ) );
}
}
else
{
d->tabPositions.clear();
d->tabStopDistance = val.toDouble();
}
}
}
@ -1320,3 +1381,7 @@ QString QgsTextFormat::asCSS( double pointToPixelMultiplier ) const
return css;
}
QgsTextFormat::Tab::Tab( double position )
: mPosition( position )
{}

View File

@ -462,6 +462,9 @@ class CORE_EXPORT QgsTextFormat
/**
* Returns the distance for tab stops.
*
* \note This value will be ignored if tabPositions() is non-empty.
*
* \see tabPositions()
* \see tabStopDistanceUnit()
* \see setTabStopDistance()
*
@ -470,8 +473,13 @@ class CORE_EXPORT QgsTextFormat
double tabStopDistance() const;
/**
* Sets the \a distance for tab stops. The units are specified using setTabStopDistanceUnit().
* Sets the \a distance for tab stops.
*
* The units are specified using setTabStopDistanceUnit().
*
* \note This value will be ignored if tabPositions() is non-empty.
*
* \see tabPositions()
* \see tabStopDistance()
* \see setTabStopDistanceUnit()
*
@ -479,10 +487,89 @@ class CORE_EXPORT QgsTextFormat
*/
void setTabStopDistance( double distance );
/**
* \ingroup core
* \brief Defines a tab position for a text format.
* \since QGIS 3.42
*/
class CORE_EXPORT Tab
{
public:
/**
* Constructor for a Tab at the specified \a position.
*/
explicit Tab( double position );
/**
* Sets the tab position.
*
* \see position()
*/
void setPosition( double position ) { mPosition = position; }
/**
* Returns the tab position.
*
* \see setPosition()
*/
double position() const { return mPosition; }
bool operator==( const QgsTextFormat::Tab &other ) const
{
return qgsDoubleNear( mPosition, other.mPosition );
}
#ifdef SIP_RUN
SIP_PYOBJECT __repr__();
% MethodCode
const QString str = QStringLiteral( "<QgsTextFormat.Tab: %1>" ).arg( sipCpp->position() );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
% End
#endif
private:
double mPosition = 0;
};
/**
* Returns the list of tab positions for tab stops.
*
* The units are specified using tabStopDistanceUnit().
*
* \note If non-empty, this list overrides any distance defined by tabStopDistance().
*
* \see setTabPositions()
* \see tabStopDistance()
* \see tabStopDistanceUnit()
* \see setTabStopDistance()
*
* \since QGIS 3.42
*/
QList< QgsTextFormat::Tab > tabPositions() const;
/**
* Sets the list of tab \a positions for tab stops.
*
* The units are specified using setTabStopDistanceUnit().
*
* \note If non-empty, this list overrides any distance defined by setTabStopDistance().
*
* \see tabPositions()
* \see setTabStopDistance()
* \see setTabStopDistanceUnit()
*
* \since QGIS 3.42
*/
void setTabPositions( const QList< QgsTextFormat::Tab > &positions );
/**
* Returns the units for the tab stop distance.
*
* \see tabStopDistance()
* \see tabPositions()
* \see setTabStopDistanceUnit()
*
* \since QGIS 3.38
@ -493,6 +580,7 @@ class CORE_EXPORT QgsTextFormat
* Sets the \a unit used for the tab stop distance.
*
* \see setTabStopDistance()
* \see setTabPositions()
* \see tabStopDistanceUnit()
*
* \since QGIS 3.38

View File

@ -283,6 +283,7 @@ class QgsTextSettingsPrivate : public QSharedData
, allowHtmlFormatting( other.allowHtmlFormatting )
, capitalization( other.capitalization )
, tabStopDistance( other.tabStopDistance )
, tabPositions( other.tabPositions )
, tabStopDistanceUnits( other.tabStopDistanceUnits )
, tabStopDistanceMapUnitScale( other.tabStopDistanceMapUnitScale )
, mDataDefinedProperties( other.mDataDefinedProperties )
@ -311,6 +312,7 @@ class QgsTextSettingsPrivate : public QSharedData
Qgis::Capitalization capitalization = Qgis::Capitalization::MixedCase;
double tabStopDistance = 6.0;
QList< QgsTextFormat::Tab > tabPositions;
Qgis::RenderUnit tabStopDistanceUnits = Qgis::RenderUnit::Percentage;
QgsMapUnitScale tabStopDistanceMapUnitScale;

View File

@ -142,6 +142,10 @@ class PyQgsTextFormat(QgisTestCase):
t.setTabStopDistance(3)
self.assertTrue(t.isValid())
t = QgsTextFormat()
t.setTabPositions([QgsTextFormat.Tab(4), QgsTextFormat.Tab(8)])
self.assertTrue(t.isValid())
t = QgsTextFormat()
t.setTabStopDistanceUnit(Qgis.RenderUnit.Points)
self.assertTrue(t.isValid())
@ -186,6 +190,12 @@ class PyQgsTextFormat(QgisTestCase):
t.setForcedItalic(True)
self.assertTrue(t.isValid())
def test_tab(self):
pos = QgsTextFormat.Tab(4)
self.assertEqual(pos, QgsTextFormat.Tab(4))
self.assertNotEqual(pos, QgsTextFormat.Tab(14))
self.assertEqual(str(pos), '<QgsTextFormat.Tab: 4>')
def createBufferSettings(self):
s = QgsTextBufferSettings()
s.setEnabled(True)
@ -718,6 +728,7 @@ class PyQgsTextFormat(QgisTestCase):
s.setForcedItalic(True)
s.setTabStopDistance(4.5)
s.setTabPositions([QgsTextFormat.Tab(5), QgsTextFormat.Tab(17)])
s.setTabStopDistanceUnit(Qgis.RenderUnit.RenderInches)
s.setTabStopDistanceMapUnitScale(QgsMapUnitScale(11, 12))
@ -844,6 +855,10 @@ class PyQgsTextFormat(QgisTestCase):
s.setTabStopDistance(120)
self.assertNotEqual(s, s2)
s = self.createFormatSettings()
s.setTabPositions([QgsTextFormat.Tab(11), QgsTextFormat.Tab(13)])
self.assertNotEqual(s, s2)
s = self.createFormatSettings()
s.setTabStopDistanceUnit(Qgis.RenderUnit.Points)
self.assertNotEqual(s, s2)
@ -883,6 +898,7 @@ class PyQgsTextFormat(QgisTestCase):
self.assertTrue(s.forcedBold())
self.assertTrue(s.forcedItalic())
self.assertEqual(s.tabStopDistance(), 4.5)
self.assertEqual(s.tabPositions(), [QgsTextFormat.Tab(5), QgsTextFormat.Tab(17)])
self.assertEqual(s.tabStopDistanceUnit(), Qgis.RenderUnit.Inches)
self.assertEqual(s.tabStopDistanceMapUnitScale(), QgsMapUnitScale(11, 12))
@ -1401,6 +1417,15 @@ class PyQgsTextFormat(QgisTestCase):
f.dataDefinedProperties().setProperty(QgsPalLayerSettings.Property.TabStopDistance, QgsProperty.fromExpression("15"))
f.updateDataDefinedProperties(context)
self.assertEqual(f.tabStopDistance(), 15)
self.assertFalse(f.tabPositions())
f.dataDefinedProperties().setProperty(QgsPalLayerSettings.Property.TabStopDistance, QgsProperty.fromValue([11, 14]))
f.updateDataDefinedProperties(context)
self.assertEqual(f.tabPositions(), [QgsTextFormat.Tab(11), QgsTextFormat.Tab(14)])
f.dataDefinedProperties().setProperty(QgsPalLayerSettings.Property.TabStopDistance, QgsProperty.fromValue(["13.5", "15.8"]))
f.updateDataDefinedProperties(context)
self.assertEqual(f.tabPositions(), [QgsTextFormat.Tab(13.5), QgsTextFormat.Tab(15.8)])
def testFontFoundFromLayer(self):
layer = createEmptyLayer()

View File

@ -2171,6 +2171,27 @@ class PyQgsTextRenderer(QgisTestCase):
format.setAllowHtmlFormatting(True)
format.setSizeUnit(QgsUnitTypes.RenderUnit.RenderPoints)
format.setTabStopDistance(5)
painter = QPainter()
ms = QgsMapSettings()
ms.setExtent(QgsRectangle(0, 0, 50, 50))
context = QgsRenderContext.fromMapSettings(ms)
context.setPainter(painter)
context.setScaleFactor(96 / 25.4) # 96 DPI
context.setFlag(QgsRenderContext.Flag.ApplyScalingWorkaroundForTextRendering, True)
self.assertTrue(
self.checkRender(format, 'tab_wrapping', text=['this\ttab\tshould\twrap'],
alignment=QgsTextRenderer.HAlignment.AlignLeft, rect=QRectF(50, 130, 350, 100),
flags=Qgis.TextRendererFlag.WrapLines)
)
def testDrawTextRectWordWrapTabPositions(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
format.setSize(30)
format.setAllowHtmlFormatting(True)
format.setSizeUnit(QgsUnitTypes.RenderUnit.RenderPoints)
format.setTabPositions([QgsTextFormat.Tab(5), QgsTextFormat.Tab(8)])
format.setTabStopDistance(5)
painter = QPainter()
ms = QgsMapSettings()
@ -2334,6 +2355,17 @@ class PyQgsTextRenderer(QgisTestCase):
'text_tab_percentage',
text=['with\ttabs', 'a\tb']))
def testDrawTabPositionsPercent(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
format.setSize(20)
format.setSizeUnit(QgsUnitTypes.RenderUnit.RenderPoints)
format.setTabPositions([QgsTextFormat.Tab(3.1), QgsTextFormat.Tab(8)])
format.setTabStopDistanceUnit(Qgis.RenderUnit.Percentage)
self.assertTrue(self.checkRender(format,
'text_tab_positions_percentage',
text=['with\tmany\ttabs', 'a\tb\tc']))
def testDrawTabFixedSize(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
@ -2345,6 +2377,28 @@ class PyQgsTextRenderer(QgisTestCase):
'text_tab_fixed_size',
text=['with\ttabs', 'a\tb']))
def testDrawTabPositionsFixedSize(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
format.setSize(20)
format.setSizeUnit(QgsUnitTypes.RenderUnit.RenderPoints)
format.setTabPositions([QgsTextFormat.Tab(20), QgsTextFormat.Tab(50)])
format.setTabStopDistanceUnit(Qgis.RenderUnit.Millimeters)
self.assertTrue(self.checkRender(format,
'text_tab_positions_fixed_size',
text=['with\tmany\ttabs', 'a\tb\tc']))
def testDrawTabPositionsFixedSizeMoreTabsThanPositions(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
format.setSize(20)
format.setSizeUnit(QgsUnitTypes.RenderUnit.RenderPoints)
format.setTabPositions([QgsTextFormat.Tab(20), QgsTextFormat.Tab(50)])
format.setTabStopDistanceUnit(Qgis.RenderUnit.Millimeters)
self.assertTrue(self.checkRender(format,
'text_tab_positions_fixed_size_more_tabs',
text=['with\tmany\ttabs', 'a\tb\tc\td\te']))
def testHtmlFormatting(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
@ -2368,6 +2422,18 @@ class PyQgsTextRenderer(QgisTestCase):
'text_tab_percentage_html',
text=['<span style="font-size: 15pt">with</span>\ttabs', ' a\tb']))
def testHtmlTabPositionsPercent(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
format.setSize(20)
format.setSizeUnit(QgsUnitTypes.RenderUnit.RenderPoints)
format.setTabPositions([QgsTextFormat.Tab(3), QgsTextFormat.Tab(8)])
format.setTabStopDistanceUnit(Qgis.RenderUnit.Percentage)
format.setAllowHtmlFormatting(True)
self.assertTrue(self.checkRender(format,
'text_tab_positions_percentage_html',
text=['<span style="font-size: 15pt">with</span>\tmany\ttabs', ' a\tb\tc']))
def testHtmlTabFixedSize(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
@ -2380,6 +2446,18 @@ class PyQgsTextRenderer(QgisTestCase):
'text_tab_fixed_size_html',
text=['<span style="font-size: 15pt">with</span>\ttabs', ' a\tb']))
def testHtmlTabPositionsFixedSize(self):
format = QgsTextFormat()
format.setFont(getTestFont('bold'))
format.setSize(20)
format.setSizeUnit(QgsUnitTypes.RenderUnit.RenderPoints)
format.setTabPositions([QgsTextFormat.Tab(25), QgsTextFormat.Tab(60)])
format.setTabStopDistanceUnit(Qgis.RenderUnit.Millimeters)
format.setAllowHtmlFormatting(True)
self.assertTrue(self.checkRender(format,
'text_tab_positions_fixed_size_html',
text=['<span style="font-size: 15pt">with</span>\tmany\ttabs', ' a\tb\tc']))
def testHtmlFormattingBuffer(self):
"""
Test drawing HTML with buffer

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB