KPimTextEdit

textutils.cpp
1/*
2 This file is part of KDE.
3
4 SPDX-FileCopyrightText: 2009 Thomas McGuire <mcguire@kde.org>
5 SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com>
6
7 SPDX-License-Identifier: LGPL-2.0-or-later
8*/
9
10#include "textutils.h"
11#include "kpimtextedit_debug.h"
12#include <QTextBlock>
13#include <QTextCharFormat>
14#include <QTextDocument>
15
16using namespace KPIMTextEdit;
17
18static bool isCharFormatFormatted(const QTextCharFormat &format, const QFont &defaultFont, const QTextCharFormat &defaultBlockFormat)
19{
20 if (!format.anchorHref().isEmpty() || format.font() != defaultFont || format.isAnchor()
21 || format.verticalAlignment() != defaultBlockFormat.verticalAlignment() || format.layoutDirection() != defaultBlockFormat.layoutDirection()
22 || format.underlineStyle() != defaultBlockFormat.underlineStyle() || format.foreground().color() != defaultBlockFormat.foreground().color()
23 || format.background().color() != defaultBlockFormat.background().color()) {
24 return true;
25 }
26
27 return false;
28}
29
30static bool isBlockFormatFormatted(const QTextBlockFormat &format, const QTextBlockFormat &defaultFormat)
31{
32 if (format.alignment() != defaultFormat.alignment() || format.layoutDirection() != defaultFormat.layoutDirection()
33 || format.indent() != defaultFormat.indent() || format.textIndent() != defaultFormat.textIndent()) {
34 return true;
35 }
36
37 return false;
38}
39
40/// @return true if the format represents a list, table, image or something like that.
41static bool isSpecial(const QTextFormat &charFormat)
42{
43 return charFormat.isFrameFormat() || charFormat.isImageFormat() || charFormat.isListFormat() || charFormat.isTableFormat()
44 || charFormat.isTableCellFormat();
45}
46
48{
49 if (!document) {
50 return false;
51 }
52
53 QTextDocument defaultTextDocument;
54 const QTextCharFormat defaultCharFormat = defaultTextDocument.begin().charFormat();
55 const QTextBlockFormat defaultBlockFormat = defaultTextDocument.begin().blockFormat();
56 const QFont defaultFont = defaultTextDocument.defaultFont();
57
58 QTextBlock block = document->firstBlock();
59 while (block.isValid()) {
60 if (isBlockFormatFormatted(block.blockFormat(), defaultBlockFormat)) {
61 return true;
62 }
63
64 if (isSpecial(block.charFormat()) || isSpecial(block.blockFormat()) || block.textList()) {
65 return true;
66 }
67
68 QTextBlock::iterator it = block.begin();
69 while (!it.atEnd()) {
70 const QTextFragment fragment = it.fragment();
71 const QTextCharFormat charFormat = fragment.charFormat();
72 if (isSpecial(charFormat)) {
73 return true;
74 }
75 if (isCharFormatFormatted(fragment.charFormat(), defaultFont, defaultCharFormat)) {
76 return true;
77 }
78
79 ++it;
80 }
81
82 block = block.next();
83 }
84
85 if (document->toHtml().contains(QLatin1StringView("<hr />"))) {
86 return true;
87 }
88
89 return false;
90}
91
92QString TextUtils::flowText(QString &wrappedText, const QString &indent, int maxLength)
93{
94 if (wrappedText.isEmpty()) {
95 return indent;
96 }
97
98 if (maxLength <= indent.length()) {
99 qCWarning(KPIMTEXTEDIT_LOG) << "indent was set to a string that is longer or the same length "
100 << "as maxLength, setting maxLength to indent.length() + 1";
101 maxLength = indent.length() + 1;
102 }
103
104 maxLength -= indent.length(); // take into account indent
105 QString result;
106 while (!wrappedText.isEmpty()) {
107 // first check for the next newline. if it's before maxLength, break there, and continue
108 int newLine = wrappedText.indexOf(QLatin1Char('\n'));
109 if (newLine > 0 && newLine <= maxLength) {
110 result += indent + wrappedText.left(newLine + 1);
111 wrappedText = wrappedText.mid(newLine + 1);
112 continue;
113 }
114 // Find the next point in the wrappedText where we have to do a line break.
115 // Start searching at maxLength position and then walk backwards looking
116 // for a space.
117 int breakPosition;
118 if (wrappedText.length() > maxLength) {
119 breakPosition = maxLength;
120 while ((breakPosition >= 0) && (wrappedText[breakPosition] != QLatin1Char(' '))) {
121 breakPosition--;
122 }
123 if (breakPosition <= 0) {
124 // Couldn't break before maxLength.
125 breakPosition = maxLength;
126 }
127 } else {
128 breakPosition = wrappedText.length();
129 }
130
131 QString line = wrappedText.left(breakPosition);
132 if (breakPosition < wrappedText.length()) {
133 wrappedText = wrappedText.mid(breakPosition);
134 } else {
135 wrappedText.clear();
136 }
137
138 // Strip leading whitespace of new lines, since that looks strange
139 if (!result.isEmpty() && line.startsWith(QLatin1Char(' '))) {
140 line.remove(0, 1);
141 }
142
143 result += indent + line + QLatin1Char('\n');
144 }
145
146 return result.left(result.length() - 1);
147}
KPIMTEXTEDIT_EXPORT bool containsFormatting(const QTextDocument *document)
Returns whether the QTextDocument document contains rich text formatting.
Definition textutils.cpp:47
KPIMTEXTEDIT_EXPORT QString flowText(QString &text, const QString &indent, int maxLength)
Changes the given text so that each line of it fits into the given maximal length.
Definition textutils.cpp:92
const QColor & color() const const
void clear()
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString left(qsizetype n) const const
qsizetype length() const const
QString mid(qsizetype position, qsizetype n) const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
iterator begin() const const
QTextBlockFormat blockFormat() const const
QTextCharFormat charFormat() const const
bool isValid() const const
QTextBlock next() const const
QTextList * textList() const const
Qt::Alignment alignment() const const
int indent() const const
qreal textIndent() const const
QString anchorHref() const const
QFont font() const const
bool isAnchor() const const
UnderlineStyle underlineStyle() const const
VerticalAlignment verticalAlignment() const const
QTextBlock begin() const const
QTextBlock firstBlock() const const
QString toHtml() const const
QBrush background() const const
QBrush foreground() const const
bool isFrameFormat() const const
bool isImageFormat() const const
bool isListFormat() const const
bool isTableCellFormat() const const
bool isTableFormat() const const
Qt::LayoutDirection layoutDirection() const const
QTextCharFormat charFormat() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:20:45 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.