src/gui/text/qtextdocument_p.h
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/text/qtextdocument_p.h	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,402 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTEXTDOCUMENT_P_H
+#define QTEXTDOCUMENT_P_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qglobal.h"
+#include "QtCore/qstring.h"
+#include "QtCore/qvector.h"
+#include "QtCore/qlist.h"
+#include "private/qobject_p.h"
+#include "private/qfragmentmap_p.h"
+#include "QtGui/qtextlayout.h"
+#include "QtGui/qtextoption.h"
+#include "private/qtextformat_p.h"
+#include "QtGui/qtextdocument.h"
+#include "QtGui/qtextobject.h"
+#include "QtCore/qmap.h"
+#include "QtCore/qvariant.h"
+#include "QtCore/qurl.h"
+#include "private/qcssparser_p.h"
+
+// #define QT_QMAP_DEBUG
+
+#ifdef QT_QMAP_DEBUG
+#include <iostream>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QTextFormatCollection;
+class QTextFormat;
+class QTextBlockFormat;
+class QTextCursorPrivate;
+class QAbstractTextDocumentLayout;
+class QTextDocument;
+class QTextFrame;
+
+#define QTextBeginningOfFrame QChar(0xfdd0)
+#define QTextEndOfFrame QChar(0xfdd1)
+
+class QTextFragmentData : public QFragment<>
+{
+public:
+    inline void initialize() {}
+    inline void invalidate() const {}
+    inline void free() {}
+    int stringPosition;
+    int format;
+};
+
+class QTextBlockData : public QFragment<3>
+{
+public:
+    inline void initialize()
+        { layout = 0; userData = 0; userState = -1; revision = 0; hidden = 0; }
+    void invalidate() const;
+    inline void free()
+    { delete layout; layout = 0; delete userData; userData = 0; }
+
+    mutable int format;
+    // ##### probably store a QTextEngine * here!
+    mutable QTextLayout *layout;
+    mutable QTextBlockUserData *userData;
+    mutable int userState;
+    mutable int revision : 31;
+    mutable uint hidden : 1;
+};
+
+
+class QAbstractUndoItem;
+
+class QTextUndoCommand
+{
+public:
+    enum Command {
+        Inserted = 0,
+        Removed = 1,
+        CharFormatChanged = 2,
+        BlockFormatChanged = 3,
+        BlockInserted = 4,
+        BlockRemoved = 5,
+        BlockAdded = 6,
+        BlockDeleted = 7,
+        GroupFormatChange = 8,
+        Custom = 256
+    };
+    enum Operation {
+        KeepCursor = 0,
+        MoveCursor = 1
+    };
+    quint16 command;
+    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
+    uint block_end : 1; // the last command in an undo block has this set to 1.
+    uint block_padding : 6; // padding since block used to be a quint8
+    quint8 operation;
+    int format;
+    quint32 strPos;
+    quint32 pos;
+    union {
+        int blockFormat;
+        quint32 length;
+        QAbstractUndoItem *custom;
+        int objectIndex;
+    };
+    quint32 revision;
+
+    bool tryMerge(const QTextUndoCommand &other);
+};
+Q_DECLARE_TYPEINFO(QTextUndoCommand, Q_PRIMITIVE_TYPE);
+
+class Q_AUTOTEST_EXPORT QTextDocumentPrivate : public QObjectPrivate
+{
+    Q_DECLARE_PUBLIC(QTextDocument)
+public:
+    typedef QFragmentMap<QTextFragmentData> FragmentMap;
+    typedef FragmentMap::ConstIterator FragmentIterator;
+    typedef QFragmentMap<QTextBlockData> BlockMap;
+
+    QTextDocumentPrivate();
+    ~QTextDocumentPrivate();
+
+    void init();
+    void clear();
+
+    void setLayout(QAbstractTextDocumentLayout *layout);
+
+    void insert(int pos, const QString &text, int format);
+    void insert(int pos, int strPos, int strLength, int format);
+    int insertBlock(int pos, int blockFormat, int charFormat, QTextUndoCommand::Operation = QTextUndoCommand::MoveCursor);
+    int insertBlock(const QChar &blockSeparator, int pos, int blockFormat, int charFormat,
+                     QTextUndoCommand::Operation op = QTextUndoCommand::MoveCursor);
+
+    void move(int from, int to, int length, QTextUndoCommand::Operation = QTextUndoCommand::MoveCursor);
+    void remove(int pos, int length, QTextUndoCommand::Operation = QTextUndoCommand::MoveCursor);
+
+    void aboutToRemoveCell(int cursorFrom, int cursorEnd);
+
+    QTextFrame *insertFrame(int start, int end, const QTextFrameFormat &format);
+    void removeFrame(QTextFrame *frame);
+
+    enum FormatChangeMode { MergeFormat, SetFormat, SetFormatAndPreserveObjectIndices };
+
+    void setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode = SetFormat);
+    void setBlockFormat(const QTextBlock &from, const QTextBlock &to,
+			const QTextBlockFormat &newFormat, FormatChangeMode mode = SetFormat);
+
+    void emitUndoAvailable(bool available);
+    void emitRedoAvailable(bool available);
+
+    int undoRedo(bool undo);
+    inline void undo() { undoRedo(true); }
+    inline void redo() { undoRedo(false); }
+    void appendUndoItem(QAbstractUndoItem *);
+    inline void beginEditBlock() { if (0 == editBlock++) ++revision; }
+    void joinPreviousEditBlock();
+    void endEditBlock();
+    void finishEdit();
+    inline bool isInEditBlock() const { return editBlock; }
+    void enableUndoRedo(bool enable);
+    inline bool isUndoRedoEnabled() const { return undoEnabled; }
+
+    inline bool isUndoAvailable() const { return undoEnabled && undoState > 0; }
+    inline bool isRedoAvailable() const { return undoEnabled && undoState < undoStack.size(); }
+
+    inline QString buffer() const { return text; }
+    QString plainText() const;
+    inline int length() const { return fragments.length(); }
+
+    inline QTextFormatCollection *formatCollection() { return &formats; }
+    inline const QTextFormatCollection *formatCollection() const { return &formats; }
+    inline QAbstractTextDocumentLayout *layout() const { return lout; }
+
+    inline FragmentIterator find(int pos) const { return fragments.find(pos); }
+    inline FragmentIterator begin() const { return fragments.begin(); }
+    inline FragmentIterator end() const { return fragments.end(); }
+
+    inline QTextBlock blocksBegin() const { return QTextBlock(const_cast<QTextDocumentPrivate *>(this), blocks.firstNode()); }
+    inline QTextBlock blocksEnd() const { return QTextBlock(const_cast<QTextDocumentPrivate *>(this), 0); }
+    inline QTextBlock blocksFind(int pos) const { return QTextBlock(const_cast<QTextDocumentPrivate *>(this), blocks.findNode(pos)); }
+    int blockCharFormatIndex(int node) const;
+
+    inline int numBlocks() const { return blocks.numNodes(); }
+
+    const BlockMap &blockMap() const { return blocks; }
+    const FragmentMap &fragmentMap() const { return fragments; }
+    BlockMap &blockMap() { return blocks; }
+    FragmentMap &fragmentMap() { return fragments; }
+
+    static const QTextBlockData *block(const QTextBlock &it) { return it.p->blocks.fragment(it.n); }
+
+    int nextCursorPosition(int position, QTextLayout::CursorMode mode) const;
+    int previousCursorPosition(int position, QTextLayout::CursorMode mode) const;
+
+    void changeObjectFormat(QTextObject *group, int format);
+
+    void setModified(bool m);
+    inline bool isModified() const { return modified; }
+
+    inline QFont defaultFont() const { return formats.defaultFont(); }
+    inline void setDefaultFont(const QFont &f) { formats.setDefaultFont(f); }
+
+private:
+    bool split(int pos);
+    bool unite(uint f);
+    void truncateUndoStack();
+
+    void insert_string(int pos, uint strPos, uint length, int format, QTextUndoCommand::Operation op);
+    int insert_block(int pos, uint strPos, int format, int blockformat, QTextUndoCommand::Operation op, int command);
+    int remove_string(int pos, uint length, QTextUndoCommand::Operation op);
+    int remove_block(int pos, int *blockformat, int command, QTextUndoCommand::Operation op);
+
+    void insert_frame(QTextFrame *f);
+    void scan_frames(int pos, int charsRemoved, int charsAdded);
+    static void clearFrame(QTextFrame *f);
+
+    void adjustDocumentChangesAndCursors(int from, int addedOrRemoved, QTextUndoCommand::Operation op);
+
+    bool wasUndoAvailable;
+    bool wasRedoAvailable;
+
+public:
+    void documentChange(int from, int length);
+
+    inline void addCursor(QTextCursorPrivate *c) { cursors.append(c); }
+    inline void removeCursor(QTextCursorPrivate *c) { cursors.removeAll(c); changedCursors.removeAll(c); }
+
+    QTextFrame *frameAt(int pos) const;
+    QTextFrame *rootFrame() const;
+
+    QTextObject *objectForIndex(int objectIndex) const;
+    QTextObject *objectForFormat(int formatIndex) const;
+    QTextObject *objectForFormat(const QTextFormat &f) const;
+
+    QTextObject *createObject(const QTextFormat &newFormat, int objectIndex = -1);
+    void deleteObject(QTextObject *object);
+
+    QTextDocument *document() { return q_func(); }
+    const QTextDocument *document() const { return q_func(); }
+
+    bool ensureMaximumBlockCount();
+
+private:
+    QTextDocumentPrivate(const QTextDocumentPrivate& m);
+    QTextDocumentPrivate& operator= (const QTextDocumentPrivate& m);
+
+    void appendUndoItem(const QTextUndoCommand &c);
+
+    void contentsChanged();
+
+    void compressPieceTable();
+
+    QString text;
+    uint unreachableCharacterCount;
+
+    QVector<QTextUndoCommand> undoStack;
+    bool undoEnabled;
+    int undoState;
+    int revision;
+    // position in undo stack of the last setModified(false) call
+    int modifiedState;
+    bool modified;
+
+    int editBlock;
+    int docChangeFrom;
+    int docChangeOldLength;
+    int docChangeLength;
+    bool framesDirty;
+
+    QTextFormatCollection formats;
+    mutable QTextFrame *rtFrame;
+    QAbstractTextDocumentLayout *lout;
+    FragmentMap fragments;
+    BlockMap blocks;
+    int initialBlockCharFormatIndex;
+
+    QList<QTextCursorPrivate*> cursors;
+    QList<QTextCursorPrivate*> changedCursors;
+    QMap<int, QTextObject *> objects;
+    QMap<QUrl, QVariant> resources;
+    QMap<QUrl, QVariant> cachedResources;
+    QString defaultStyleSheet;
+
+    int lastBlockCount;
+
+public:
+    QTextOption defaultTextOption;
+#ifndef QT_NO_CSSPARSER
+    QCss::StyleSheet parsedDefaultStyleSheet;
+#endif
+    int maximumBlockCount;
+    uint needsEnsureMaximumBlockCount : 1;
+    uint inContentsChange : 1;
+    QSizeF pageSize;
+    QString title;
+    QString url;
+    qreal indentWidth;
+    qreal documentMargin;
+
+    void mergeCachedResources(const QTextDocumentPrivate *priv);
+
+    friend class QTextHtmlExporter;
+    friend class QTextCursor;
+};
+
+class QTextTable;
+class QTextHtmlExporter
+{
+public:
+    QTextHtmlExporter(const QTextDocument *_doc);
+
+    enum ExportMode {
+        ExportEntireDocument,
+        ExportFragment
+    };
+
+    QString toHtml(const QByteArray &encoding, ExportMode mode = ExportEntireDocument);
+
+private:
+    enum StyleMode { EmitStyleTag, OmitStyleTag };
+    enum FrameType { TextFrame, TableFrame, RootFrame };
+
+    void emitFrame(QTextFrame::Iterator frameIt);
+    void emitTextFrame(const QTextFrame *frame);
+    void emitBlock(const QTextBlock &block);
+    void emitTable(const QTextTable *table);
+    void emitFragment(const QTextFragment &fragment);
+
+    void emitBlockAttributes(const QTextBlock &block);
+    bool emitCharFormatStyle(const QTextCharFormat &format);
+    void emitTextLength(const char *attribute, const QTextLength &length);
+    void emitAlignment(Qt::Alignment alignment);
+    void emitFloatStyle(QTextFrameFormat::Position pos, StyleMode mode = EmitStyleTag);
+    void emitMargins(const QString &top, const QString &bottom, const QString &left, const QString &right);
+    void emitAttribute(const char *attribute, const QString &value);
+    void emitFrameStyle(const QTextFrameFormat &format, FrameType frameType);
+    void emitBorderStyle(QTextFrameFormat::BorderStyle style);
+    void emitPageBreakPolicy(QTextFormat::PageBreakFlags policy);
+
+    void emitFontFamily(const QString &family);
+
+    void emitBackgroundAttribute(const QTextFormat &format);
+    QString findUrlForImage(const QTextDocument *doc, qint64 cacheKey, bool isPixmap);
+
+    QString html;
+    QTextCharFormat defaultCharFormat;
+    const QTextDocument *doc;
+    bool fragmentMarkers;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTEXTDOCUMENT_P_H