23#include <QTextDocument>
33 mBlocks.append( block );
44 document.
reserve( lines.size() );
45 for (
const QString &line : lines )
55#define TAB_REPLACEMENT_MARKER " ignore_me_i_am_a_tab "
61 document.
reserve( lines.size() );
63 for (
const QString &l : std::as_const( lines ) )
70 QTextDocument sourceDoc;
81 const thread_local QRegularExpression sRxPixelsToPtFix( QStringLiteral(
"(word-spacing|line-height|margin-top|margin-bottom|margin-left|margin-right):\\s*(-?\\d+(?:\\.\\d+)?)(?![%\\d])([a-zA-Z]*)" ) );
82 line.replace( sRxPixelsToPtFix, QStringLiteral(
"\\1: \\2px" ) );
83 const thread_local QRegularExpression sRxMarginPixelsToPtFix( QStringLiteral(
"margin:\\s*(-?\\d+(?:\\.\\d+)?)([a-zA-Z]*)\\s*(-?\\d+(?:\\.\\d+)?)([a-zA-Z]*)\\s*(-?\\d+(?:\\.\\d+)?)([a-zA-Z]*)\\s*(-?\\d+(?:\\.\\d+)?)([a-zA-Z]*)" ) );
84 line.replace( sRxMarginPixelsToPtFix, QStringLiteral(
"margin: \\1px \\3px \\5px \\7px" ) );
88 line.prepend( QStringLiteral(
"<style>p, h1, h2, h3, h4, h5, h6 { margin: 0pt; }</style>" ) );
90 sourceDoc.setHtml( line );
92 QTextBlock sourceBlock = sourceDoc.firstBlock();
96 const int headingLevel = sourceBlock.blockFormat().headingLevel();
98 if ( headingLevel > 0 )
100 switch ( headingLevel )
125 auto it = sourceBlock.begin();
128 while ( !it.atEnd() )
130 const QTextFragment fragment = it.fragment();
131 if ( fragment.isValid() )
134 const QString fragmentText = fragment.text();
135 if ( fragmentText.contains( QStringLiteral(
"\u2028" ) ) )
138 const QStringList
splitLines = fragmentText.split( QStringLiteral(
"\u2028" ), Qt::SplitBehaviorFlags::SkipEmptyParts );
140 for (
const QString &splitLine : std::as_const(
splitLines ) )
147 previousFormat = &document.
at( document.
size() - 1 ).
at( 0 ).characterFormat();
157 if ( previousFormat )
160 newFormat.overrideWith( *previousFormat );
167 for (
const QString &part : tabSplit )
169 if ( !part.isEmpty() )
172 block.
append( splitFragment );
174 if ( index != tabSplit.size() - 1 )
184 splitFragment.
setText( splitLine );
188 if ( previousFormat )
191 newFormat.overrideWith( *previousFormat );
195 block.
append( splitFragment );
215 for (
const QString &part : tabSplit )
217 if ( !part.isEmpty() )
220 block.
append( tmpFragment );
222 if ( index != tabSplit.size() - 1 )
236 block.
append( tmpFragment );
242 if ( !block.
empty() )
245 sourceBlock = sourceBlock.next();
246 if ( !sourceBlock.isValid() )
265 if ( doc.
size() > 0 )
272 mBlocks.append( block );
277 mBlocks.push_back( block );
282 mBlocks.insert( index, block );
287 mBlocks.insert( index, block );
292 mBlocks.reserve( count );
297 return mBlocks.at( i );
307 return mBlocks.size();
312 QStringList textLines;
313 textLines.reserve( mBlocks.size() );
319 line.append( fragment.text() );
328 const QVector< QgsTextBlock > prevBlocks = mBlocks;
330 mBlocks.reserve( prevBlocks.size() );
337 QStringList thisParts;
338 if ( !wrapCharacter.isEmpty() && wrapCharacter != QLatin1String(
"\n" ) )
341 const QStringList lines = fragment.text().split( wrapCharacter );
342 for (
const QString &line : lines )
344 thisParts.append( line.split(
'\n' ) );
349 thisParts = fragment.text().split(
'\n' );
353 if ( autoWrapLength != 0 )
355 QStringList autoWrappedLines;
356 autoWrappedLines.reserve( thisParts.count() );
357 for (
const QString &line : std::as_const( thisParts ) )
359 autoWrappedLines.append(
QgsStringUtils::wordWrap( line, autoWrapLength, useMaxLineLengthWhenAutoWrapping ).split(
'\n' ) );
361 thisParts = autoWrappedLines;
364 if ( thisParts.empty() )
366 else if ( thisParts.size() == 1 )
367 destinationBlock.
append( fragment );
370 if ( !thisParts.at( 0 ).isEmpty() )
373 append( destinationBlock );
374 destinationBlock.
clear();
375 for (
int i = 1 ; i < thisParts.size() - 1; ++i )
381 destinationBlock.
append(
QgsTextFragment( thisParts.at( thisParts.size() - 1 ), fragment.characterFormat() ) );
384 append( destinationBlock );
392 block.applyCapitalization( capitalization );
398 return std::any_of( mBlocks.begin(), mBlocks.end(), [](
const QgsTextBlock & block ) { return block.hasBackgrounds(); } );
402QVector< QgsTextBlock >::const_iterator QgsTextDocument::begin()
const
404 return mBlocks.begin();
407QVector< QgsTextBlock >::const_iterator QgsTextDocument::end()
const
409 return mBlocks.end();
Capitalization
String capitalization options.
static QString wordWrap(const QString &string, int length, bool useMaxLineLength=true, const QString &customDelimiter=QString())
Automatically wraps a string by inserting new line characters at appropriate locations in the string.
Stores information relating to individual block formatting.
Represents a block of text consisting of one or more QgsTextFragment objects.
void clear()
Clears the block, removing all its contents.
static QgsTextBlock fromPlainText(const QString &text, const QgsTextCharacterFormat &format=QgsTextCharacterFormat())
Constructor for QgsTextBlock consisting of a plain text, and optional character format.
void setBlockFormat(const QgsTextBlockFormat &format)
Sets the block format for the fragment.
void append(const QgsTextFragment &fragment)
Appends a fragment to the block.
bool empty() const
Returns true if the block is empty.
Stores information relating to individual character formatting.
void overrideWith(const QgsTextCharacterFormat &other)
Override all the default/unset properties of the current character format with the settings from anot...
void setFontPercentageSize(double size)
Sets the font percentage size (as fraction of inherited font size).
Represents a document consisting of one or more QgsTextBlock objects.
void splitLines(const QString &wrapCharacter, int autoWrapLength=0, bool useMaxLineLengthWhenAutoWrapping=true)
Splits lines of text in the document to separate lines, using a specified wrap character (wrapCharact...
QgsTextBlock & operator[](int index)
Returns the block at the specified index.
const QgsTextBlock & at(int index) const
Returns the block at the specified index.
void reserve(int count)
Reserves the specified count of blocks for optimised block appending.
QStringList toPlainText() const
Returns a list of plain text lines of text representing the document.
int size() const
Returns the number of blocks in the document.
static QgsTextDocument fromHtml(const QStringList &lines)
Constructor for QgsTextDocument consisting of a set of HTML formatted lines.
static QgsTextDocument fromPlainText(const QStringList &lines)
Constructor for QgsTextDocument consisting of a set of plain text lines.
void append(const QgsTextBlock &block)
Appends a block to the document.
void insert(int index, const QgsTextBlock &block)
Inserts a block into the document, at the specified index.
static QgsTextDocument fromTextAndFormat(const QStringList &lines, const QgsTextFormat &format)
Constructor for QgsTextDocument consisting of a set of lines, respecting settings from a text format.
void applyCapitalization(Qgis::Capitalization capitalization)
Applies a capitalization style to the document's text.
bool hasBackgrounds() const
Returns true if any blocks or fragments in the document have background brushes set.
Container for all settings relating to text rendering.
Qgis::Capitalization capitalization() const
Returns the text capitalization style.
bool allowHtmlFormatting() const
Returns true if text should be treated as a HTML document and HTML tags should be used for formatting...
Stores a fragment of document along with formatting overrides to be used when rendering the fragment.
void setText(const QString &text)
Sets the text content of the fragment.
void setCharacterFormat(const QgsTextCharacterFormat &format)
Sets the character format for the fragment.
const QgsTextCharacterFormat & characterFormat() const
Returns the character formatting for the fragment.
#define TAB_REPLACEMENT_MARKER