File indexing completed on 2024-05-05 05:21:42
0001 /* 0002 This file is part of KDE. 0003 0004 SPDX-FileCopyrightText: 2009 Thomas McGuire <mcguire@kde.org> 0005 SPDX-FileCopyrightText: 2010 Stephen Kelly <steveire@gmail.com> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "textutils.h" 0011 #include "kpimtextedit_debug.h" 0012 #include <QTextBlock> 0013 #include <QTextCharFormat> 0014 #include <QTextDocument> 0015 0016 using namespace KPIMTextEdit; 0017 0018 static bool isCharFormatFormatted(const QTextCharFormat &format, const QFont &defaultFont, const QTextCharFormat &defaultBlockFormat) 0019 { 0020 if (!format.anchorHref().isEmpty() || format.font() != defaultFont || format.isAnchor() 0021 || format.verticalAlignment() != defaultBlockFormat.verticalAlignment() || format.layoutDirection() != defaultBlockFormat.layoutDirection() 0022 || format.underlineStyle() != defaultBlockFormat.underlineStyle() || format.foreground().color() != defaultBlockFormat.foreground().color() 0023 || format.background().color() != defaultBlockFormat.background().color()) { 0024 return true; 0025 } 0026 0027 return false; 0028 } 0029 0030 static bool isBlockFormatFormatted(const QTextBlockFormat &format, const QTextBlockFormat &defaultFormat) 0031 { 0032 if (format.alignment() != defaultFormat.alignment() || format.layoutDirection() != defaultFormat.layoutDirection() 0033 || format.indent() != defaultFormat.indent() || format.textIndent() != defaultFormat.textIndent()) { 0034 return true; 0035 } 0036 0037 return false; 0038 } 0039 0040 /// @return true if the format represents a list, table, image or something like that. 0041 static bool isSpecial(const QTextFormat &charFormat) 0042 { 0043 return charFormat.isFrameFormat() || charFormat.isImageFormat() || charFormat.isListFormat() || charFormat.isTableFormat() 0044 || charFormat.isTableCellFormat(); 0045 } 0046 0047 bool TextUtils::containsFormatting(const QTextDocument *document) 0048 { 0049 if (!document) { 0050 return false; 0051 } 0052 0053 QTextDocument defaultTextDocument; 0054 const QTextCharFormat defaultCharFormat = defaultTextDocument.begin().charFormat(); 0055 const QTextBlockFormat defaultBlockFormat = defaultTextDocument.begin().blockFormat(); 0056 const QFont defaultFont = defaultTextDocument.defaultFont(); 0057 0058 QTextBlock block = document->firstBlock(); 0059 while (block.isValid()) { 0060 if (isBlockFormatFormatted(block.blockFormat(), defaultBlockFormat)) { 0061 return true; 0062 } 0063 0064 if (isSpecial(block.charFormat()) || isSpecial(block.blockFormat()) || block.textList()) { 0065 return true; 0066 } 0067 0068 QTextBlock::iterator it = block.begin(); 0069 while (!it.atEnd()) { 0070 const QTextFragment fragment = it.fragment(); 0071 const QTextCharFormat charFormat = fragment.charFormat(); 0072 if (isSpecial(charFormat)) { 0073 return true; 0074 } 0075 if (isCharFormatFormatted(fragment.charFormat(), defaultFont, defaultCharFormat)) { 0076 return true; 0077 } 0078 0079 ++it; 0080 } 0081 0082 block = block.next(); 0083 } 0084 0085 if (document->toHtml().contains(QLatin1StringView("<hr />"))) { 0086 return true; 0087 } 0088 0089 return false; 0090 } 0091 0092 QString TextUtils::flowText(QString &wrappedText, const QString &indent, int maxLength) 0093 { 0094 if (wrappedText.isEmpty()) { 0095 return indent; 0096 } 0097 0098 if (maxLength <= indent.length()) { 0099 qCWarning(KPIMTEXTEDIT_LOG) << "indent was set to a string that is longer or the same length " 0100 << "as maxLength, setting maxLength to indent.length() + 1"; 0101 maxLength = indent.length() + 1; 0102 } 0103 0104 maxLength -= indent.length(); // take into account indent 0105 QString result; 0106 while (!wrappedText.isEmpty()) { 0107 // first check for the next newline. if it's before maxLength, break there, and continue 0108 int newLine = wrappedText.indexOf(QLatin1Char('\n')); 0109 if (newLine > 0 && newLine <= maxLength) { 0110 result += indent + wrappedText.left(newLine + 1); 0111 wrappedText = wrappedText.mid(newLine + 1); 0112 continue; 0113 } 0114 // Find the next point in the wrappedText where we have to do a line break. 0115 // Start searching at maxLength position and then walk backwards looking 0116 // for a space. 0117 int breakPosition; 0118 if (wrappedText.length() > maxLength) { 0119 breakPosition = maxLength; 0120 while ((breakPosition >= 0) && (wrappedText[breakPosition] != QLatin1Char(' '))) { 0121 breakPosition--; 0122 } 0123 if (breakPosition <= 0) { 0124 // Couldn't break before maxLength. 0125 breakPosition = maxLength; 0126 } 0127 } else { 0128 breakPosition = wrappedText.length(); 0129 } 0130 0131 QString line = wrappedText.left(breakPosition); 0132 if (breakPosition < wrappedText.length()) { 0133 wrappedText = wrappedText.mid(breakPosition); 0134 } else { 0135 wrappedText.clear(); 0136 } 0137 0138 // Strip leading whitespace of new lines, since that looks strange 0139 if (!result.isEmpty() && line.startsWith(QLatin1Char(' '))) { 0140 line.remove(0, 1); 0141 } 0142 0143 result += indent + line + QLatin1Char('\n'); 0144 } 0145 0146 return result.left(result.length() - 1); 0147 }