25#include <QTextDocument>
32 : mBlocks( other.mBlocks )
38 : mBlocks( std::move( other.mBlocks ) )
48 mBlocks = other.mBlocks;
57 mBlocks = std::move( other.mBlocks );
63 mBlocks.append( block );
74 document.
reserve( lines.size() );
75 for (
const QString &line : lines )
85#define TAB_REPLACEMENT_MARKER " ignore_me_i_am_a_tab "
89#define TAB_REPLACEMENT_MARKER_RX " ?ignore_me_i_am_a_tab ?"
95 document.
reserve( lines.size() );
97 for (
const QString &l : std::as_const( lines ) )
104 QTextDocument sourceDoc;
116 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]*)" ) );
117 line.replace( sRxPixelsToPtFix, QStringLiteral(
"\\1: \\2px" ) );
118 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]*)" ) );
119 line.replace( sRxMarginPixelsToPtFix, QStringLiteral(
"margin: \\1px \\3px \\5px \\7px" ) );
123 line.prepend( QStringLiteral(
"<style>p, h1, h2, h3, h4, h5, h6 { margin: 0pt; }</style>" ) );
125 sourceDoc.setHtml( line );
127 QTextBlock sourceBlock = sourceDoc.firstBlock();
131 const int headingLevel = sourceBlock.blockFormat().headingLevel();
133 if ( headingLevel > 0 )
135 switch ( headingLevel )
160 auto it = sourceBlock.begin();
163 while ( !it.atEnd() )
165 const QTextFragment fragment = it.fragment();
166 if ( fragment.isValid() )
169 const QString fragmentText = fragment.text();
170 if ( fragmentText.contains( QStringLiteral(
"\u2028" ) ) )
173 const QStringList
splitLines = fragmentText.split( QStringLiteral(
"\u2028" ), Qt::SplitBehaviorFlags::SkipEmptyParts );
175 for (
const QString &splitLine : std::as_const(
splitLines ) )
192 if ( previousFormat )
200 const QStringList tabSplit = splitLine.split( sTabReplacementMarkerRx );
202 for (
const QString &part : tabSplit )
204 if ( !part.isEmpty() )
207 block.
append( splitFragment );
209 if ( index != tabSplit.size() - 1 )
219 splitFragment.
setText( splitLine );
223 if ( previousFormat )
230 block.
append( splitFragment );
248 const QStringList tabSplit = fragmentText.split( sTabReplacementMarkerRx );
250 for (
const QString &part : tabSplit )
252 if ( !part.isEmpty() )
255 block.
append( tmpFragment );
257 if ( index != tabSplit.size() - 1 )
271 block.
append( tmpFragment );
277 if ( !block.
empty() )
280 sourceBlock = sourceBlock.next();
281 if ( !sourceBlock.isValid() )
300 if ( doc.
size() > 0 )
312 mBlocks.push_back( block );
317 mBlocks.insert( index, block );
322 mBlocks.insert( index, block );
327 mBlocks.reserve( count );
332 return mBlocks.
at( i );
342 return mBlocks.
size();
347 QStringList textLines;
348 textLines.reserve( mBlocks.size() );
354 line.append( fragment.text() );
363 const QVector< QgsTextBlock > prevBlocks = mBlocks;
365 mBlocks.reserve( prevBlocks.size() );
372 QStringList thisParts;
373 if ( !wrapCharacter.isEmpty() && wrapCharacter != QLatin1String(
"\n" ) )
376 const QStringList lines = fragment.text().split( wrapCharacter );
377 for (
const QString &line : lines )
379 thisParts.append( line.split(
'\n' ) );
384 thisParts = fragment.text().split(
'\n' );
388 if ( autoWrapLength != 0 )
390 QStringList autoWrappedLines;
391 autoWrappedLines.reserve( thisParts.count() );
392 for (
const QString &line : std::as_const( thisParts ) )
394 autoWrappedLines.append(
QgsStringUtils::wordWrap( line, autoWrapLength, useMaxLineLengthWhenAutoWrapping ).split(
'\n' ) );
396 thisParts = autoWrappedLines;
399 if ( thisParts.empty() )
401 else if ( thisParts.size() == 1 )
402 destinationBlock.
append( fragment );
405 if ( !thisParts.at( 0 ).isEmpty() )
408 append( destinationBlock );
409 destinationBlock.
clear();
410 for (
int i = 1 ; i < thisParts.size() - 1; ++i )
416 destinationBlock.
append(
QgsTextFragment( thisParts.at( thisParts.size() - 1 ), fragment.characterFormat() ) );
419 append( destinationBlock );
427 block.applyCapitalization( capitalization );
433 return std::any_of( mBlocks.begin(), mBlocks.end(), [](
const QgsTextBlock & block ) { return block.hasBackgrounds(); } );
437QVector< QgsTextBlock >::const_iterator QgsTextDocument::begin()
const
439 return mBlocks.begin();
442QVector< QgsTextBlock >::const_iterator QgsTextDocument::end()
const
444 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.
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