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 "
59#define TAB_REPLACEMENT_MARKER_RX " ?ignore_me_i_am_a_tab ?"
65 document.
reserve( lines.size() );
67 for (
const QString &l : std::as_const( lines ) )
74 QTextDocument sourceDoc;
86 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]*)" ) );
87 line.replace( sRxPixelsToPtFix, QStringLiteral(
"\\1: \\2px" ) );
88 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]*)" ) );
89 line.replace( sRxMarginPixelsToPtFix, QStringLiteral(
"margin: \\1px \\3px \\5px \\7px" ) );
93 line.prepend( QStringLiteral(
"<style>p, h1, h2, h3, h4, h5, h6 { margin: 0pt; }</style>" ) );
95 sourceDoc.setHtml( line );
97 QTextBlock sourceBlock = sourceDoc.firstBlock();
101 const int headingLevel = sourceBlock.blockFormat().headingLevel();
103 if ( headingLevel > 0 )
105 switch ( headingLevel )
130 auto it = sourceBlock.begin();
133 while ( !it.atEnd() )
135 const QTextFragment fragment = it.fragment();
136 if ( fragment.isValid() )
139 const QString fragmentText = fragment.text();
140 if ( fragmentText.contains( QStringLiteral(
"\u2028" ) ) )
143 const QStringList
splitLines = fragmentText.split( QStringLiteral(
"\u2028" ), Qt::SplitBehaviorFlags::SkipEmptyParts );
145 for (
const QString &splitLine : std::as_const(
splitLines ) )
152 previousFormat = &document.
at( document.
size() - 1 ).
at( 0 ).characterFormat();
162 if ( previousFormat )
165 newFormat.overrideWith( *previousFormat );
170 const QStringList tabSplit = splitLine.split( sTabReplacementMarkerRx );
172 for (
const QString &part : tabSplit )
174 if ( !part.isEmpty() )
177 block.
append( splitFragment );
179 if ( index != tabSplit.size() - 1 )
189 splitFragment.
setText( splitLine );
193 if ( previousFormat )
196 newFormat.overrideWith( *previousFormat );
200 block.
append( splitFragment );
218 const QStringList tabSplit = fragmentText.split( sTabReplacementMarkerRx );
220 for (
const QString &part : tabSplit )
222 if ( !part.isEmpty() )
225 block.
append( tmpFragment );
227 if ( index != tabSplit.size() - 1 )
241 block.
append( tmpFragment );
247 if ( !block.
empty() )
250 sourceBlock = sourceBlock.next();
251 if ( !sourceBlock.isValid() )
270 if ( doc.
size() > 0 )
277 mBlocks.append( block );
282 mBlocks.push_back( block );
287 mBlocks.insert( index, block );
292 mBlocks.insert( index, block );
297 mBlocks.reserve( count );
302 return mBlocks.at( i );
312 return mBlocks.size();
317 QStringList textLines;
318 textLines.reserve( mBlocks.size() );
324 line.append( fragment.text() );
333 const QVector< QgsTextBlock > prevBlocks = mBlocks;
335 mBlocks.reserve( prevBlocks.size() );
342 QStringList thisParts;
343 if ( !wrapCharacter.isEmpty() && wrapCharacter != QLatin1String(
"\n" ) )
346 const QStringList lines = fragment.text().split( wrapCharacter );
347 for (
const QString &line : lines )
349 thisParts.append( line.split(
'\n' ) );
354 thisParts = fragment.text().split(
'\n' );
358 if ( autoWrapLength != 0 )
360 QStringList autoWrappedLines;
361 autoWrappedLines.reserve( thisParts.count() );
362 for (
const QString &line : std::as_const( thisParts ) )
364 autoWrappedLines.append(
QgsStringUtils::wordWrap( line, autoWrapLength, useMaxLineLengthWhenAutoWrapping ).split(
'\n' ) );
366 thisParts = autoWrappedLines;
369 if ( thisParts.empty() )
371 else if ( thisParts.size() == 1 )
372 destinationBlock.
append( fragment );
375 if ( !thisParts.at( 0 ).isEmpty() )
378 append( destinationBlock );
379 destinationBlock.
clear();
380 for (
int i = 1 ; i < thisParts.size() - 1; ++i )
386 destinationBlock.
append(
QgsTextFragment( thisParts.at( thisParts.size() - 1 ), fragment.characterFormat() ) );
389 append( destinationBlock );
397 block.applyCapitalization( capitalization );
403 return std::any_of( mBlocks.begin(), mBlocks.end(), [](
const QgsTextBlock & block ) { return block.hasBackgrounds(); } );
407QVector< QgsTextBlock >::const_iterator QgsTextDocument::begin()
const
409 return mBlocks.begin();
412QVector< QgsTextBlock >::const_iterator QgsTextDocument::end()
const
414 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_RX
#define TAB_REPLACEMENT_MARKER