This set of changes is to enable the capability of setting a fragment's visibility...
[qt:ganesh-qt.git] / src / gui / text / qtextdocument_p.h
1 /****************************************************************************
2 **
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QTEXTDOCUMENT_P_H
43 #define QTEXTDOCUMENT_P_H
44
45 //
46 //  W A R N I N G
47 //  -------------
48 //
49 // This file is not part of the Qt API.  It exists purely as an
50 // implementation detail.  This header file may change from version to
51 // version without notice, or even be removed.
52 //
53 // We mean it.
54 //
55
56 #include "QtCore/qglobal.h"
57 #include "QtCore/qstring.h"
58 #include "QtCore/qvector.h"
59 #include "QtCore/qlist.h"
60 #include "private/qobject_p.h"
61 #include "private/qfragmentmap_p.h"
62 #include "QtGui/qtextlayout.h"
63 #include "QtGui/qtextoption.h"
64 #include "private/qtextformat_p.h"
65 #include "QtGui/qtextdocument.h"
66 #include "QtGui/qtextobject.h"
67 #include "QtCore/qmap.h"
68 #include "QtCore/qvariant.h"
69 #include "QtCore/qurl.h"
70 #include "private/qcssparser_p.h"
71
72 // #define QT_QMAP_DEBUG
73
74 #ifdef QT_QMAP_DEBUG
75 #include <iostream>
76 #endif
77
78 QT_BEGIN_NAMESPACE
79
80 class QTextFormatCollection;
81 class QTextFormat;
82 class QTextBlockFormat;
83 class QTextCursorPrivate;
84 class QAbstractTextDocumentLayout;
85 class QTextDocument;
86 class QTextFrame;
87
88 #define QTextBeginningOfFrame QChar(0xfdd0)
89 #define QTextEndOfFrame QChar(0xfdd1)
90
91 class QTextFragmentData : public QFragment<>
92 {
93 public:
94     inline void initialize() { hidden = false; }
95     inline void invalidate() const {}
96     inline void free() {}
97     int stringPosition;
98     int format;
99     mutable bool hidden;
100 };
101
102 class QTextBlockData : public QFragment<3>
103 {
104 public:
105     inline void initialize()
106         { layout = 0; userData = 0; userState = -1; revision = 0; hidden = 0; }
107     void invalidate() const;
108     inline void free()
109     { delete layout; layout = 0; delete userData; userData = 0; }
110
111     mutable int format;
112     // ##### probably store a QTextEngine * here!
113     mutable QTextLayout *layout;
114     mutable QTextBlockUserData *userData;
115     mutable int userState;
116     mutable int revision : 31;
117     mutable uint hidden : 1;
118 };
119
120
121 class QAbstractUndoItem;
122
123 class QTextUndoCommand
124 {
125 public:
126     enum Command {
127         Inserted = 0,
128         Removed = 1,
129         CharFormatChanged = 2,
130         BlockFormatChanged = 3,
131         BlockInserted = 4,
132         BlockRemoved = 5,
133         BlockAdded = 6,
134         BlockDeleted = 7,
135         GroupFormatChange = 8,
136         Custom = 256
137     };
138     enum Operation {
139         KeepCursor = 0,
140         MoveCursor = 1
141     };
142     quint16 command;
143     uint block_part : 1; // all commands that are part of an undo block (including the first and the last one) have this set to 1
144     uint block_end : 1; // the last command in an undo block has this set to 1.
145     uint block_padding : 6; // padding since block used to be a quint8
146     quint8 operation;
147     int format;
148     quint32 strPos;
149     quint32 pos;
150     union {
151         int blockFormat;
152         quint32 length;
153         QAbstractUndoItem *custom;
154         int objectIndex;
155     };
156     quint32 revision;
157
158     bool tryMerge(const QTextUndoCommand &other);
159 };
160 Q_DECLARE_TYPEINFO(QTextUndoCommand, Q_PRIMITIVE_TYPE);
161
162 class Q_AUTOTEST_EXPORT QTextDocumentPrivate : public QObjectPrivate
163 {
164     Q_DECLARE_PUBLIC(QTextDocument)
165 public:
166     typedef QFragmentMap<QTextFragmentData> FragmentMap;
167     typedef FragmentMap::ConstIterator FragmentIterator;
168     typedef QFragmentMap<QTextBlockData> BlockMap;
169
170     QTextDocumentPrivate();
171     ~QTextDocumentPrivate();
172
173     void init();
174     void clear();
175
176     void setLayout(QAbstractTextDocumentLayout *layout);
177
178     void insert(int pos, const QString &text, int format);
179     void insert(int pos, int strPos, int strLength, int format);
180     int insertBlock(int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation = QTextUndoCommand::MoveCursor);
181     int insertBlock(const QChar &blockSeparator, int pos, int blockFormat, int charFormat,
182                      QTextUndoCommand::Operation op = QTextUndoCommand::MoveCursor);
183
184     void move(int from, int to, int length, QTextUndoCommand::Operation = QTextUndoCommand::MoveCursor);
185     void remove(int pos, int length, QTextUndoCommand::Operation = QTextUndoCommand::MoveCursor);
186
187     void aboutToRemoveCell(int cursorFrom, int cursorEnd);
188
189     QTextFrame *insertFrame(int start, int end, const QTextFrameFormat &format);
190     void removeFrame(QTextFrame *frame);
191
192     enum FormatChangeMode { MergeFormat, SetFormat, SetFormatAndPreserveObjectIndices };
193
194     void setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode = SetFormat);
195     void setBlockFormat(const QTextBlock &from, const QTextBlock &to,
196                         const QTextBlockFormat &newFormat, FormatChangeMode mode = SetFormat);
197
198     void emitUndoAvailable(bool available);
199     void emitRedoAvailable(bool available);
200
201     int undoRedo(bool undo);
202     inline void undo() { undoRedo(true); }
203     inline void redo() { undoRedo(false); }
204     void appendUndoItem(QAbstractUndoItem *);
205     inline void beginEditBlock() { if (0 == editBlock++) ++revision; }
206     void joinPreviousEditBlock();
207     void endEditBlock();
208     void finishEdit();
209     inline bool isInEditBlock() const { return editBlock; }
210     void enableUndoRedo(bool enable);
211     inline bool isUndoRedoEnabled() const { return undoEnabled; }
212
213     inline bool isUndoAvailable() const { return undoEnabled && undoState > 0; }
214     inline bool isRedoAvailable() const { return undoEnabled && undoState < undoStack.size(); }
215
216     inline int availableUndoSteps() const { return undoEnabled ? undoState : 0; }
217     inline int availableRedoSteps() const { return undoEnabled ? qMax(undoStack.size() - undoState - 1, 0) : 0; }
218
219     inline QString buffer() const { return text; }
220     QString plainText() const;
221     inline int length() const { return fragments.length(); }
222
223     inline QTextFormatCollection *formatCollection() { return &formats; }
224     inline const QTextFormatCollection *formatCollection() const { return &formats; }
225     inline QAbstractTextDocumentLayout *layout() const { return lout; }
226
227     inline FragmentIterator find(int pos) const { return fragments.find(pos); }
228     inline FragmentIterator begin() const { return fragments.begin(); }
229     inline FragmentIterator end() const { return fragments.end(); }
230
231     inline QTextBlock blocksBegin() const { return QTextBlock(const_cast<QTextDocumentPrivate *>(this), blocks.firstNode()); }
232     inline QTextBlock blocksEnd() const { return QTextBlock(const_cast<QTextDocumentPrivate *>(this), 0); }
233     inline QTextBlock blocksFind(int pos) const { return QTextBlock(const_cast<QTextDocumentPrivate *>(this), blocks.findNode(pos)); }
234     int blockCharFormatIndex(int node) const;
235
236     inline int numBlocks() const { return blocks.numNodes(); }
237
238     const BlockMap &blockMap() const { return blocks; }
239     const FragmentMap &fragmentMap() const { return fragments; }
240     BlockMap &blockMap() { return blocks; }
241     FragmentMap &fragmentMap() { return fragments; }
242
243     static const QTextBlockData *block(const QTextBlock &it) { return it.p->blocks.fragment(it.n); }
244
245     int nextCursorPosition(int position, QTextLayout::CursorMode mode) const;
246     int previousCursorPosition(int position, QTextLayout::CursorMode mode) const;
247
248     void changeObjectFormat(QTextObject *group, int format);
249
250     void setModified(bool m);
251     inline bool isModified() const { return modified; }
252
253     inline QFont defaultFont() const { return formats.defaultFont(); }
254     inline void setDefaultFont(const QFont &f) { formats.setDefaultFont(f); }
255
256 private:
257     bool split(int pos);
258     bool unite(uint f);
259     void truncateUndoStack();
260
261     void insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op);
262     int insert_block(int pos, uint strPos, int format, int blockformat, QTextUndoCommand::Operation op, int command);
263     int remove_string(int pos, uint length, QTextUndoCommand::Operation op);
264     int remove_block(int pos, int *blockformat, int command, QTextUndoCommand::Operation op);
265
266     void insert_frame(QTextFrame *f);
267     void scan_frames(int pos, int charsRemoved, int charsAdded);
268     static void clearFrame(QTextFrame *f);
269
270     void adjustDocumentChangesAndCursors(int from, int addedOrRemoved, QTextUndoCommand::Operation op);
271
272     bool wasUndoAvailable;
273     bool wasRedoAvailable;
274
275 public:
276     void documentChange(int from, int length);
277
278     inline void addCursor(QTextCursorPrivate *c) { cursors.append(c); }
279     inline void removeCursor(QTextCursorPrivate *c) { cursors.removeAll(c); changedCursors.removeAll(c); }
280
281     QTextFrame *frameAt(int pos) const;
282     QTextFrame *rootFrame() const;
283
284     QTextObject *objectForIndex(int objectIndex) const;
285     QTextObject *objectForFormat(int formatIndex) const;
286     QTextObject *objectForFormat(const QTextFormat &f) const;
287
288     QTextObject *createObject(const QTextFormat &newFormat, int objectIndex = -1);
289     void deleteObject(QTextObject *object);
290
291     QTextDocument *document() { return q_func(); }
292     const QTextDocument *document() const { return q_func(); }
293
294     bool ensureMaximumBlockCount();
295
296 private:
297     QTextDocumentPrivate(const QTextDocumentPrivate& m);
298     QTextDocumentPrivate& operator= (const QTextDocumentPrivate& m);
299
300     void appendUndoItem(const QTextUndoCommand &c);
301
302     void contentsChanged();
303
304     void compressPieceTable();
305
306     QString text;
307     uint unreachableCharacterCount;
308
309     QVector<QTextUndoCommand> undoStack;
310     bool undoEnabled;
311     int undoState;
312     int revision;
313     // position in undo stack of the last setModified(false) call
314     int modifiedState;
315     bool modified;
316
317     int editBlock;
318     int docChangeFrom;
319     int docChangeOldLength;
320     int docChangeLength;
321     bool framesDirty;
322
323     QTextFormatCollection formats;
324     mutable QTextFrame *rtFrame;
325     QAbstractTextDocumentLayout *lout;
326     FragmentMap fragments;
327     BlockMap blocks;
328     int initialBlockCharFormatIndex;
329
330     QList<QTextCursorPrivate*> cursors;
331     QList<QTextCursorPrivate*> changedCursors;
332     QMap<int, QTextObject *> objects;
333     QMap<QUrl, QVariant> resources;
334     QMap<QUrl, QVariant> cachedResources;
335     QString defaultStyleSheet;
336
337     int lastBlockCount;
338
339 public:
340     QTextOption defaultTextOption;
341 #ifndef QT_NO_CSSPARSER
342     QCss::StyleSheet parsedDefaultStyleSheet;
343 #endif
344     int maximumBlockCount;
345     uint needsEnsureMaximumBlockCount : 1;
346     uint inContentsChange : 1;
347     QSizeF pageSize;
348     QString title;
349     QString url;
350     qreal indentWidth;
351     qreal documentMargin;
352
353     void mergeCachedResources(const QTextDocumentPrivate *priv);
354
355     friend class QTextHtmlExporter;
356     friend class QTextCursor;
357 };
358
359 class QTextTable;
360 class QTextHtmlExporter
361 {
362 public:
363     QTextHtmlExporter(const QTextDocument *_doc);
364
365     enum ExportMode {
366         ExportEntireDocument,
367         ExportFragment
368     };
369
370     QString toHtml(const QByteArray &encoding, ExportMode mode = ExportEntireDocument);
371
372 private:
373     enum StyleMode { EmitStyleTag, OmitStyleTag };
374     enum FrameType { TextFrame, TableFrame, RootFrame };
375
376     void emitFrame(QTextFrame::Iterator frameIt);
377     void emitTextFrame(const QTextFrame *frame);
378     void emitBlock(const QTextBlock &block);
379     void emitTable(const QTextTable *table);
380     void emitFragment(const QTextFragment &fragment);
381
382     void emitBlockAttributes(const QTextBlock &block);
383     bool emitCharFormatStyle(const QTextCharFormat &format);
384     void emitTextLength(const char *attribute, const QTextLength &length);
385     void emitAlignment(Qt::Alignment alignment);
386     void emitFloatStyle(QTextFrameFormat::Position pos, StyleMode mode = EmitStyleTag);
387     void emitMargins(const QString &top, const QString &bottom, const QString &left, const QString &right);
388     void emitAttribute(const char *attribute, const QString &value);
389     void emitFrameStyle(const QTextFrameFormat &format, FrameType frameType);
390     void emitBorderStyle(QTextFrameFormat::BorderStyle style);
391     void emitPageBreakPolicy(QTextFormat::PageBreakFlags policy);
392
393     void emitFontFamily(const QString &family);
394
395     void emitBackgroundAttribute(const QTextFormat &format);
396     QString findUrlForImage(const QTextDocument *doc, qint64 cacheKey, bool isPixmap);
397
398     QString html;
399     QTextCharFormat defaultCharFormat;
400     const QTextDocument *doc;
401     bool fragmentMarkers;
402 };
403
404 QT_END_NAMESPACE
405
406 #endif // QTEXTDOCUMENT_P_H