1 /**************************************************************************** 2 ** 3 ** Copyright (C) 2016 The Qt Company Ltd. 4 ** Contact: https://www.qt.io/licensing/ 5 ** 6 ** This file is part of the QtGui module of the Qt Toolkit. 7 ** 8 ** $QT_BEGIN_LICENSE:LGPL$ 9 ** Commercial License Usage 10 ** Licensees holding valid commercial Qt licenses may use this file in 11 ** accordance with the commercial license agreement provided with the 12 ** Software or, alternatively, in accordance with the terms contained in 13 ** a written agreement between you and The Qt Company. For licensing terms 14 ** and conditions see https://www.qt.io/terms-conditions. For further 15 ** information use the contact form at https://www.qt.io/contact-us. 16 ** 17 ** GNU Lesser General Public License Usage 18 ** Alternatively, this file may be used under the terms of the GNU Lesser 19 ** General Public License version 3 as published by the Free Software 20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the 21 ** packaging of this file. Please review the following information to 22 ** ensure the GNU Lesser General Public License version 3 requirements 23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. 24 ** 25 ** GNU General Public License Usage 26 ** Alternatively, this file may be used under the terms of the GNU 27 ** General Public License version 2.0 or (at your option) the GNU General 28 ** Public license version 3 or any later version approved by the KDE Free 29 ** Qt Foundation. The licenses are as published by the Free Software 30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 31 ** included in the packaging of this file. Please review the following 32 ** information to ensure the GNU General Public License requirements will 33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and 34 ** https://www.gnu.org/licenses/gpl-3.0.html. 35 ** 36 ** $QT_END_LICENSE$ 37 ** 38 ****************************************************************************/ 39 40 #ifndef QTEXTDOCUMENTFRAGMENT_P_H 41 #define QTEXTDOCUMENTFRAGMENT_P_H 42 43 // 44 // W A R N I N G 45 // ------------- 46 // 47 // This file is not part of the Qt API. It exists purely as an 48 // implementation detail. This header file may change from version to 49 // version without notice, or even be removed. 50 // 51 // We mean it. 52 // 53 54 #include <QtGui/private/qtguiglobal_p.h> 55 #include "QtGui/qtextdocument.h" 56 #include "private/qtexthtmlparser_p.h" 57 #include "private/qtextdocument_p.h" 58 #include "QtGui/qtexttable.h" 59 #include "QtCore/qatomic.h" 60 #include "QtCore/qlist.h" 61 #include "QtCore/qmap.h" 62 #include "QtCore/qpointer.h" 63 #include "QtCore/qvarlengtharray.h" 64 #include "QtCore/qdatastream.h" 65 66 QT_BEGIN_NAMESPACE 67 68 class QTextDocumentFragmentPrivate; 69 70 class QTextCopyHelper 71 { 72 public: 73 QTextCopyHelper(const QTextCursor &_source, const QTextCursor &_destination, bool forceCharFormat = false, const QTextCharFormat &fmt = QTextCharFormat()); 74 75 void copy(); 76 77 private: 78 void appendFragments(int pos, int endPos); 79 int appendFragment(int pos, int endPos, int objectIndex = -1); 80 int convertFormatIndex(const QTextFormat &oldFormat, int objectIndexToSet = -1); 81 inline int convertFormatIndex(int oldFormatIndex, int objectIndexToSet = -1) 82 { return convertFormatIndex(src->formatCollection()->format(oldFormatIndex), objectIndexToSet); } convertFormat(const QTextFormat & fmt)83 inline QTextFormat convertFormat(const QTextFormat &fmt) 84 { return dst->formatCollection()->format(convertFormatIndex(fmt)); } 85 86 int insertPos; 87 88 bool forceCharFormat; 89 int primaryCharFormatIndex; 90 91 QTextCursor cursor; 92 QTextDocumentPrivate *dst; 93 QTextDocumentPrivate *src; 94 QTextFormatCollection &formatCollection; 95 const QString originalText; 96 QMap<int, int> objectIndexMap; 97 }; 98 99 class QTextDocumentFragmentPrivate 100 { 101 public: 102 QTextDocumentFragmentPrivate(const QTextCursor &cursor = QTextCursor()); ~QTextDocumentFragmentPrivate()103 inline ~QTextDocumentFragmentPrivate() { delete doc; } 104 105 void insert(QTextCursor &cursor) const; 106 107 QAtomicInt ref; 108 QTextDocument *doc; 109 110 uint importedFromPlainText : 1; 111 private: 112 Q_DISABLE_COPY_MOVE(QTextDocumentFragmentPrivate) 113 }; 114 115 #ifndef QT_NO_TEXTHTMLPARSER 116 117 class QTextHtmlImporter : public QTextHtmlParser 118 { 119 struct Table; 120 public: 121 enum ImportMode { 122 ImportToFragment, 123 ImportToDocument 124 }; 125 126 QTextHtmlImporter(QTextDocument *_doc, const QString &html, 127 ImportMode mode, 128 const QTextDocument *resourceProvider = nullptr); 129 130 void import(); 131 132 private: 133 bool closeTag(); 134 135 Table scanTable(int tableNodeIdx); 136 137 enum ProcessNodeResult { ContinueWithNextNode, ContinueWithCurrentNode, ContinueWithNextSibling }; 138 139 void appendBlock(const QTextBlockFormat &format, QTextCharFormat charFmt = QTextCharFormat()); 140 bool appendNodeText(); 141 142 ProcessNodeResult processBlockNode(); 143 ProcessNodeResult processSpecialNodes(); 144 145 struct List 146 { ListList147 inline List() : listNode(0) {} 148 QTextListFormat format; 149 int listNode; 150 QPointer<QTextList> list; 151 }; 152 friend class QTypeInfo<List>; 153 QVector<List> lists; 154 int indent; 155 int headingLevel; 156 157 // insert a named anchor the next time we emit a char format, 158 // either in a block or in regular text 159 QStringList namedAnchors; 160 161 #ifdef Q_CC_SUN 162 friend struct QTextHtmlImporter::Table; 163 #endif 164 struct TableCellIterator 165 { tableTableCellIterator166 inline TableCellIterator(QTextTable *t = nullptr) : table(t), row(0), column(0) {} 167 168 inline TableCellIterator &operator++() { 169 if (atEnd()) 170 return *this; 171 do { 172 const QTextTableCell cell = table->cellAt(row, column); 173 if (!cell.isValid()) 174 break; 175 column += cell.columnSpan(); 176 if (column >= table->columns()) { 177 column = 0; 178 ++row; 179 } 180 } while (row < table->rows() && table->cellAt(row, column).row() != row); 181 182 return *this; 183 } 184 atEndTableCellIterator185 inline bool atEnd() const { return table == nullptr || row >= table->rows(); } 186 cellTableCellIterator187 QTextTableCell cell() const { return table->cellAt(row, column); } 188 189 QTextTable *table; 190 int row; 191 int column; 192 }; 193 friend class QTypeInfo<TableCellIterator>; 194 195 friend struct Table; 196 struct Table 197 { TableTable198 Table() : isTextFrame(false), rows(0), columns(0), currentRow(0), lastIndent(0) {} 199 QPointer<QTextFrame> frame; 200 bool isTextFrame; 201 int rows; 202 int columns; 203 int currentRow; // ... for buggy html (see html_skipCell testcase) 204 TableCellIterator currentCell; 205 int lastIndent; 206 }; 207 friend class QTypeInfo<Table>; 208 QVector<Table> tables; 209 210 struct RowColSpanInfo 211 { 212 int row, col; 213 int rowSpan, colSpan; 214 }; 215 friend class QTypeInfo<RowColSpanInfo>; 216 217 enum WhiteSpace 218 { 219 RemoveWhiteSpace, 220 CollapseWhiteSpace, 221 PreserveWhiteSpace 222 }; 223 224 WhiteSpace compressNextWhitespace; 225 226 QTextDocument *doc; 227 QTextCursor cursor; 228 QTextHtmlParserNode::WhiteSpaceMode wsm; 229 ImportMode importMode; 230 bool hasBlock; 231 bool forceBlockMerging; 232 bool blockTagClosed; 233 int currentNodeIdx; 234 const QTextHtmlParserNode *currentNode; 235 }; 236 Q_DECLARE_TYPEINFO(QTextHtmlImporter::List, Q_MOVABLE_TYPE); 237 Q_DECLARE_TYPEINFO(QTextHtmlImporter::TableCellIterator, Q_PRIMITIVE_TYPE); 238 Q_DECLARE_TYPEINFO(QTextHtmlImporter::Table, Q_MOVABLE_TYPE); 239 Q_DECLARE_TYPEINFO(QTextHtmlImporter::RowColSpanInfo, Q_PRIMITIVE_TYPE); 240 241 QT_END_NAMESPACE 242 #endif // QT_NO_TEXTHTMLPARSER 243 244 #endif // QTEXTDOCUMENTFRAGMENT_P_H 245