26#include <QTextDocument>
28using namespace Qt::StringLiterals;
35 : mBlocks( other.mBlocks )
41 : mBlocks( std::move( other.mBlocks ) )
51 mBlocks = other.mBlocks;
60 mBlocks = std::move( other.mBlocks );
66 mBlocks.append( block );
77 document.
reserve( lines.size() );
78 for (
const QString &line : lines )
88#define TAB_REPLACEMENT_MARKER " ignore_me_i_am_a_tab "
92#define TAB_REPLACEMENT_MARKER_RX " ?ignore_me_i_am_a_tab ?"
98 document.
reserve( lines.size() );
100 for (
const QString &l : std::as_const( lines ) )
107 QTextDocument sourceDoc;
119 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 );
120 line.replace( sRxPixelsToPtFix, u
"\\1: \\2px"_s );
121 const thread_local QRegularExpression sRxMarginPixelsToPtFix( 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 );
122 line.replace( sRxMarginPixelsToPtFix, u
"margin: \\1px \\3px \\5px \\7px"_s );
126 line.prepend( u
"<style>p, h1, h2, h3, h4, h5, h6 { margin: 0pt; }</style>"_s );
128 sourceDoc.setHtml( line );
130 QTextBlock sourceBlock = sourceDoc.firstBlock();
134 const int headingLevel = sourceBlock.blockFormat().headingLevel();
136 if ( headingLevel > 0 )
138 switch ( headingLevel )
163 auto it = sourceBlock.begin();
166 while ( !it.atEnd() )
168 const QTextFragment fragment = it.fragment();
169 if ( fragment.isValid() )
172 const QString fragmentText = fragment.text();
173 if ( fragmentText.contains( u
"\u2028"_s ) )
176 const QStringList
splitLines = fragmentText.split( u
"\u2028"_s, Qt::SplitBehaviorFlags::SkipEmptyParts );
178 for (
const QString &splitLine : std::as_const(
splitLines ) )
195 if ( previousFormat )
203 const QStringList tabSplit = splitLine.split( sTabReplacementMarkerRx );
205 for (
const QString &part : tabSplit )
207 if ( !part.isEmpty() )
210 block.
append( splitFragment );
212 if ( index != tabSplit.size() - 1 )
222 splitFragment.
setText( splitLine );
226 if ( previousFormat )
233 block.
append( splitFragment );
251 const QStringList tabSplit = fragmentText.split( sTabReplacementMarkerRx );
253 for (
const QString &part : tabSplit )
255 if ( !part.isEmpty() )
258 block.
append( tmpFragment );
260 if ( index != tabSplit.size() - 1 )
274 block.
append( tmpFragment );
280 if ( !block.
empty() )
283 sourceBlock = sourceBlock.next();
284 if ( !sourceBlock.isValid() )
303 if ( doc.
size() > 0 )
315 mBlocks.push_back( block );
320 mBlocks.insert( index, block );
325 mBlocks.insert( index, block );
330 mBlocks.reserve( count );
335 return mBlocks.
at( i );
345 return mBlocks.
size();
350 QStringList textLines;
351 textLines.reserve( mBlocks.size() );
357 line.append( fragment.text() );
366 const QVector< QgsTextBlock > prevBlocks = mBlocks;
368 mBlocks.reserve( prevBlocks.size() );
375 QStringList thisParts;
376 if ( !wrapCharacter.isEmpty() && wrapCharacter !=
"\n"_L1 )
379 const QStringList lines = fragment.text().split( wrapCharacter );
380 for (
const QString &line : lines )
382 thisParts.append( line.split(
'\n' ) );
387 thisParts = fragment.text().split(
'\n' );
391 if ( autoWrapLength != 0 )
393 QStringList autoWrappedLines;
394 autoWrappedLines.reserve( thisParts.count() );
395 for (
const QString &line : std::as_const( thisParts ) )
397 autoWrappedLines.append(
QgsStringUtils::wordWrap( line, autoWrapLength, useMaxLineLengthWhenAutoWrapping ).split(
'\n' ) );
399 thisParts = autoWrappedLines;
402 if ( thisParts.empty() )
404 else if ( thisParts.size() == 1 )
405 destinationBlock.
append( fragment );
408 if ( !thisParts.at( 0 ).isEmpty() )
411 append( destinationBlock );
412 destinationBlock.
clear();
413 for (
int i = 1 ; i < thisParts.size() - 1; ++i )
419 destinationBlock.
append(
QgsTextFragment( thisParts.at( thisParts.size() - 1 ), fragment.characterFormat() ) );
422 append( destinationBlock );
428 QVector<QgsTextDocument> res;
429 res.reserve( mBlocks.size() );
441 block.applyCapitalization( capitalization );
447 return std::any_of( mBlocks.begin(), mBlocks.end(), [](
const QgsTextBlock & block ) { return block.hasBackgrounds(); } );
451QVector< QgsTextBlock >::const_iterator QgsTextDocument::begin()
const
453 return mBlocks.begin();
456QVector< QgsTextBlock >::const_iterator QgsTextDocument::end()
const
458 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