QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
qgstextdocument.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgstextdocument.cpp
3 -----------------
4 begin : May 2020
5 copyright : (C) Nyall Dawson
6 email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgstextdocument.h"
17#include "qgis.h"
18#include "qgsstringutils.h"
19#include "qgstextblock.h"
20#include "qgstextfragment.h"
21
22#include <QTextDocument>
23#include <QTextBlock>
24
25
27
29
31{
32 mBlocks.append( block );
33}
34
36{
37 mBlocks.append( QgsTextBlock( fragment ) );
38}
39
41{
42 QgsTextDocument document;
43 document.reserve( lines.size() );
44 for ( const QString &line : lines )
45 document.append( QgsTextBlock( QgsTextFragment( line ) ) );
46 return document;
47}
48
49QgsTextDocument QgsTextDocument::fromHtml( const QStringList &lines )
50{
51 QgsTextDocument document;
52
53 document.reserve( lines.size() );
54 for ( const QString &line : lines )
55 {
56 // QTextDocument is a very heavy way of parsing HTML + css (it's heavily geared toward an editable text document,
57 // and includes a LOT of calculations we don't need, when all we're after is a HTML + CSS style parser).
58 // TODO - try to find an alternative library we can use here
59 QTextDocument sourceDoc;
60 sourceDoc.setHtml( line );
61
62 QTextBlock sourceBlock = sourceDoc.firstBlock();
63 while ( true )
64 {
65 auto it = sourceBlock.begin();
66 QgsTextBlock block;
67 while ( !it.atEnd() )
68 {
69 const QTextFragment fragment = it.fragment();
70 if ( fragment.isValid() )
71 {
72 block.append( QgsTextFragment( fragment ) );
73 }
74 it++;
75 }
76 if ( !block.empty() )
77 document.append( block );
78
79 sourceBlock = sourceBlock.next();
80 if ( !sourceBlock.isValid() )
81 break;
82 }
83 }
84 return document;
85}
86
88{
89 mBlocks.append( block );
90}
91
93{
94 mBlocks.push_back( block );
95}
96
97void QgsTextDocument::reserve( int count )
98{
99 mBlocks.reserve( count );
100}
101
103{
104 return mBlocks.at( i );
105}
106
108{
109 return mBlocks[i];
110}
111
113{
114 return mBlocks.size();
115}
116
118{
119 QStringList textLines;
120 textLines.reserve( mBlocks.size() );
121 for ( const QgsTextBlock &block : mBlocks )
122 {
123 QString line;
124 for ( const QgsTextFragment &fragment : block )
125 {
126 line.append( fragment.text() );
127 }
128 textLines << line;
129 }
130 return textLines;
131}
132
133void QgsTextDocument::splitLines( const QString &wrapCharacter, int autoWrapLength, bool useMaxLineLengthWhenAutoWrapping )
134{
135 const QVector< QgsTextBlock > prevBlocks = mBlocks;
136 mBlocks.clear();
137 mBlocks.reserve( prevBlocks.size() );
138 for ( const QgsTextBlock &block : prevBlocks )
139 {
140 QgsTextBlock destinationBlock;
141 for ( const QgsTextFragment &fragment : block )
142 {
143 QStringList thisParts;
144 if ( !wrapCharacter.isEmpty() && wrapCharacter != QLatin1String( "\n" ) )
145 {
146 //wrap on both the wrapchr and new line characters
147 const QStringList lines = fragment.text().split( wrapCharacter );
148 for ( const QString &line : lines )
149 {
150 thisParts.append( line.split( '\n' ) );
151 }
152 }
153 else
154 {
155 thisParts = fragment.text().split( '\n' );
156 }
157
158 // apply auto wrapping to each manually created line
159 if ( autoWrapLength != 0 )
160 {
161 QStringList autoWrappedLines;
162 autoWrappedLines.reserve( thisParts.count() );
163 for ( const QString &line : std::as_const( thisParts ) )
164 {
165 autoWrappedLines.append( QgsStringUtils::wordWrap( line, autoWrapLength, useMaxLineLengthWhenAutoWrapping ).split( '\n' ) );
166 }
167 thisParts = autoWrappedLines;
168 }
169
170 if ( thisParts.empty() )
171 continue;
172 else if ( thisParts.size() == 1 )
173 destinationBlock.append( fragment );
174 else
175 {
176 if ( !thisParts.at( 0 ).isEmpty() )
177 destinationBlock.append( QgsTextFragment( thisParts.at( 0 ), fragment.characterFormat() ) );
178
179 append( destinationBlock );
180 destinationBlock.clear();
181 for ( int i = 1 ; i < thisParts.size() - 1; ++i )
182 {
183 append( QgsTextBlock( QgsTextFragment( thisParts.at( i ), fragment.characterFormat() ) ) );
184 }
185 destinationBlock.append( QgsTextFragment( thisParts.at( thisParts.size() - 1 ), fragment.characterFormat() ) );
186 }
187 }
188 append( destinationBlock );
189 }
190}
191
193{
194 for ( QgsTextBlock &block : mBlocks )
195 {
196 block.applyCapitalization( capitalization );
197 }
198}
199
201QVector< QgsTextBlock >::const_iterator QgsTextDocument::begin() const
202{
203 return mBlocks.begin();
204}
205
206QVector< QgsTextBlock >::const_iterator QgsTextDocument::end() const
207{
208 return mBlocks.end();
209}
Capitalization
String capitalization options.
Definition: qgis.h:1762
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.
Represents a block of text consisting of one or more QgsTextFragment objects.
Definition: qgstextblock.h:36
void clear()
Clears the block, removing all its contents.
void append(const QgsTextFragment &fragment)
Appends a fragment to the block.
bool empty() const
Returns true if the block is empty.
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 applyCapitalization(Qgis::Capitalization capitalization)
Applies a capitalization style to the document's text.
Stores a fragment of text along with formatting overrides to be used when rendering the fragment.