26#include <QTextDocument>
28using namespace Qt::StringLiterals;
35 : mBlocks( other.mBlocks )
39 : mBlocks( std::move( other.mBlocks ) )
47 mBlocks = other.mBlocks;
56 mBlocks = std::move( other.mBlocks );
62 mBlocks.append( block );
73 document.
reserve( lines.size() );
74 for (
const QString &line : lines )
84#define TAB_REPLACEMENT_MARKER " ignore_me_i_am_a_tab "
88#define TAB_REPLACEMENT_MARKER_RX " ?ignore_me_i_am_a_tab ?"
94 document.
reserve( lines.size() );
96 for (
const QString &l : std::as_const( lines ) )
103 QTextDocument sourceDoc;
115 const thread_local QRegularExpression sRxPixelsToPtFix( u
"(word-spacing|line-height|margin-top|margin-bottom|margin-left|margin-right):\\s*(-?\\d+(?:\\.\\d+)?)(?![%\\d])([a-zA-Z]*)"_s );
116 line.replace( sRxPixelsToPtFix, u
"\\1: \\2px"_s );
117 const thread_local QRegularExpression sRxMarginPixelsToPtFix(
118 u
"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]*)"_s
120 line.replace( sRxMarginPixelsToPtFix, u
"margin: \\1px \\3px \\5px \\7px"_s );
124 line.prepend( u
"<style>p, h1, h2, h3, h4, h5, h6 { margin: 0pt; }</style>"_s );
126 sourceDoc.setHtml( line );
128 QTextBlock sourceBlock = sourceDoc.firstBlock();
132 const int headingLevel = sourceBlock.blockFormat().headingLevel();
134 if ( headingLevel > 0 )
136 switch ( headingLevel )
161 auto it = sourceBlock.begin();
164 while ( !it.atEnd() )
166 const QTextFragment fragment = it.fragment();
167 if ( fragment.isValid() )
170 const QString fragmentText = fragment.text();
171 if ( fragmentText.contains( u
"\u2028"_s ) )
174 const QStringList
splitLines = fragmentText.split( u
"\u2028"_s, Qt::SplitBehaviorFlags::SkipEmptyParts );
176 for (
const QString &splitLine : std::as_const(
splitLines ) )
193 if ( previousFormat )
201 const QStringList tabSplit = splitLine.split( sTabReplacementMarkerRx );
203 for (
const QString &part : tabSplit )
205 if ( !part.isEmpty() )
208 block.
append( splitFragment );
210 if ( index != tabSplit.size() - 1 )
220 splitFragment.
setText( splitLine );
224 if ( previousFormat )
231 block.
append( splitFragment );
249 const QStringList tabSplit = fragmentText.split( sTabReplacementMarkerRx );
251 for (
const QString &part : tabSplit )
253 if ( !part.isEmpty() )
256 block.
append( tmpFragment );
258 if ( index != tabSplit.size() - 1 )
272 block.
append( tmpFragment );
278 if ( !block.
empty() )
281 sourceBlock = sourceBlock.next();
282 if ( !sourceBlock.isValid() )
301 if ( doc.
size() > 0 )
313 mBlocks.push_back( block );
318 mBlocks.insert( index, block );
323 mBlocks.insert( index, block );
328 mBlocks.reserve( count );
333 return mBlocks.
at( i );
343 return mBlocks.
size();
348 QStringList textLines;
349 textLines.reserve( mBlocks.size() );
355 line.append( fragment.text() );
364 const QVector< QgsTextBlock > prevBlocks = mBlocks;
366 mBlocks.reserve( prevBlocks.size() );
373 QStringList thisParts;
374 if ( !wrapCharacter.isEmpty() && wrapCharacter !=
"\n"_L1 )
377 const QStringList lines = fragment.text().split( wrapCharacter );
378 for (
const QString &line : lines )
380 thisParts.append( line.split(
'\n' ) );
385 thisParts = fragment.text().split(
'\n' );
389 if ( autoWrapLength != 0 )
391 QStringList autoWrappedLines;
392 autoWrappedLines.reserve( thisParts.count() );
393 for (
const QString &line : std::as_const( thisParts ) )
395 autoWrappedLines.append(
QgsStringUtils::wordWrap( line, autoWrapLength, useMaxLineLengthWhenAutoWrapping ).split(
'\n' ) );
397 thisParts = autoWrappedLines;
400 if ( thisParts.empty() )
402 else if ( thisParts.size() == 1 )
403 destinationBlock.
append( fragment );
406 if ( !thisParts.at( 0 ).isEmpty() )
409 append( destinationBlock );
410 destinationBlock.
clear();
411 for (
int i = 1; i < thisParts.size() - 1; ++i )
417 destinationBlock.
append(
QgsTextFragment( thisParts.at( thisParts.size() - 1 ), fragment.characterFormat() ) );
420 append( destinationBlock );
426 QVector<QgsTextDocument> res;
427 res.reserve( mBlocks.size() );
439 block.applyCapitalization( capitalization );
445 return std::any_of( mBlocks.begin(), mBlocks.end(), [](
const QgsTextBlock &block ) { return block.hasBackgrounds(); } );
449QVector< QgsTextBlock >::const_iterator QgsTextDocument::begin()
const
451 return mBlocks.begin();
454QVector< QgsTextBlock >::const_iterator QgsTextDocument::end()
const
456 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.
int size() const
Returns the number of fragments in the block.
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.
const QgsTextFragment & at(int index) const
Returns the fragment at the specified index.
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).
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.
QgsTextDocument & operator=(const QgsTextDocument &other)
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.
QVector< QgsTextDocument > splitBlocksToDocuments() const
Splits the text document, such that each block in the document becomes a separate document of its own...
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_RX
#define TAB_REPLACEMENT_MARKER